tip:
这里题意有两个细节就是:1.出现名字次数[不指定是哪些名字]2.名字是不相互包含的


解题思路:我们先看看样例:szymonikaszymonikatomck;[长度23]
其中:szymon和monika出现两次,tomck出现一次


这时候我们就会联想到最短路:将每个单词看成一个点,对于任意两个单词i和j我们有两种选择就是把i接到j后面,或者把j接到i后面,边权就是拼接之后[最长的公共部分会重叠]字符串增加的长度

举个例子:设szymon是3号点,monika是1号点,当1号接在3号后面时候变成了szymonika相对3号点来说怎加了3,所以从3连一条长度为3的有向边到1,反过来如果是3接到1就是monikaszymon,增长了6,就是1到3长度为6


初始转态是没有字符串,我们可以设立一个虚拟源点0。跑floyed算法,名字出现m次就是跑过条边之后的最短路。因为m很大我们可以用矩阵快速幂优化


note:建立自环边就是自己接在自己后面在用hash求最长公共部分的时候要从minlen-1开始枚举因为重合了不算两个,算一个而已。


#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <limits.h>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define Mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define hash Hash
#define next Next
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 1e6 + 10, MOD = 998244353;
const long double eps = 1e-5;
const int p = 2333;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x)
{x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{read(first);read(args...);
}
string s[220];
ull Hash[220][100010];
ull bin[100010];
int n, m;
struct matrix {ll g[220][220];matrix(){for(int i = 0;i < 220;i++)for(int j = 0;j < 220;j++)g[i][j] = LLF;}
}obj;matrix Floyed(matrix a, matrix b)
{matrix ans;for(int k = 0; k <= n; ++ k)for(int i = 0; i <= n; ++ i)for(int j = 0; j <= n; ++ j)ans.g[i][j] = min(ans.g[i][j],a.g[i][k]+b.g[k][j]);return ans;
}matrix Pow(matrix a, int k)
{matrix c;for(int i = 0; i <= n; ++ i) c.g[i][i] = 0;while(k){if(k & 1) c = Floyed(c,a);a = Floyed(a,a);k >>= 1;}return c;
}inline ull get_hash(ull *h, int l, int r)
{return h[r] - h[l - 1] * bin[r - l + 1];
}inline void geth(int num, string s)
{Hash[num][0] = s[0] - 'a' + 1;for(int i = 1; i < s.length(); ++ i)Hash[num][i] = Hash[num][i - 1] * p + (s[i] - 'a' + 1);
}inline void build(int from, int to)
{int sf = s[from].length();int st = s[to].length();int l = 0, r = min(sf,st);for(int i = r - 1; i >= 1; -- i)if(get_hash(Hash[from],sf-i,sf-1) == get_hash(Hash[to],0,i-1)){l = i;break;    }obj.g[from][to] = st - l;
}int main()
{read(n,m);bin[0] = 1;for(int i = 1; i < 100010; ++ i) bin[i] = bin[i - 1] * p;for(int i = 1; i <= n; ++ i) cin >> s[i], geth(i,s[i]);for(int from = 1; from <= n; ++ from)for(int to = 1; to <= n; ++ to)build(from, to);for(int i = 1; i <= n; ++ i)obj.g[0][i] = s[i].length(); matrix ans = Pow(obj,m);ll res = LLF;for(int i = 0; i <= n; ++ i)res = min(res,ans.g[0][i]); cout << res << endl; return 0;
} 

[Poi2010]Hamsters[字符串hash+floyed+矩阵快速幂]相关推荐

  1. 【BZOJ2085】【POI2010】—Hamsters(哈希+矩阵快速幂)

    传送门 Description Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算.现在Tz想好了要出现 ...

  2. bzoj2085: [Poi2010]Hamsters(hash+矩阵快速幂)

    传送门 题意:给定n个长度总和不超过1e5的字符串,求一个最短的母串,使所有字符串的出现次数之和=m 这n个字符串保证不互相包含,n≤200 思路: 由于保证字符串两两不相互包含. 因此我们可以考虑 ...

  3. bzoj 4002: [JLOI2015]有意义的字符串(特征根法+矩阵快速幂)

    4002: [JLOI2015]有意义的字符串 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 960  Solved: 415 [Submit][S ...

  4. BZOJ.4180.字符串计数(后缀自动机 二分 矩阵快速幂/倍增Floyd)

    题目链接 先考虑 假设S确定,使构造S操作次数最小的方案应是:对T建SAM,S在SAM上匹配,如果有S的转移就转移,否则操作数++,回到根节点继续匹配S.即每次操作一定是一次极大匹配. 简单证明:假设 ...

  5. [HNOI2008]GT考试[矩阵快速幂+kmp优化的dp]

    解题思路:假如说我们用f[i]表示长度为i的串能组合成无不吉利数字的组合的个数的话我们无法找到f[i]和f[i+1]的关系,就是我们下一位填某个数字会不会出现不吉利串,这就和你前面的串末尾于不吉利串重 ...

  6. 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂

    题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...

  7. 51nod 算法马拉松18 B 非010串 矩阵快速幂

    51nod 算法马拉松18 B 非010串 矩阵快速幂 非010串 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 如果一个01字符串满足不存在010这样的子串,那么称它为非010串 ...

  8. poj 2778 AC自动机+矩阵快速幂

    题目链接:https://vjudge.net/problem/POJ-2778 题意:输入n和m表示n个病毒,和一个长为m的字符串,里面只可以有'A','C','G','T' 这四个字符,现在问这个 ...

  9. 矩阵快速幂的一份小结

    矩阵真是个好东西!虽然矩乘的复杂度有点难看... ... 这几天也做了不少矩阵题目,还是有几道好题目的.不过我打算从入门开始. 矩阵乘法:A[i][k]*B[k][j]=C[i][j];(A的第i行的 ...

最新文章

  1. 【快速上手mac必备】常用优质mac软件推荐(音视频、办公、软件开发、辅助工具、系统管理、云存储)
  2. Spring Boot注入自定义properties文件配置
  3. Numpy-浅拷贝和深拷贝
  4. 2018年计算机学校迎新标语,2018学校迎新标语大全.doc
  5. windows下mongodb安装与使用整理
  6. 基于CSS3实现水平轮播效果
  7. 52 - 算法 - 数据结构 vector
  8. learning java AWT 布局管理器 GridLayout
  9. 【求助】想知道Xcode怎么像devc一样调试程序
  10. Python 之 字典(dict)的创建、字典生成式、复制添加更新删除、查询遍历比较等
  11. Java之时间格式转换
  12. 计算机主板的位置,电脑主板在哪个位置(主板工作原理和主要种类)
  13. QTTabBar功能是灰色,无法启用的解决办法
  14. C语言输出图形:宝塔形(三角形)回文数字。即:第一行1,第二行121,第三行12321……
  15. linux无线网卡消失,Linux下无线网卡无法开启解决办法
  16. cad画流程图的插件_PIDCAD工艺流程图绘图软件
  17. wsl 设置阿里云源
  18. 芒果超媒前三季营收102亿:同比降12% 互联网广告收入降26%
  19. 机器学习作业之波士顿房价(boston)数据分析与绘图(注释我都写了这么多,我不信你还看不懂?)
  20. java查找算法:线性查找

热门文章

  1. 双机热备实验——(VRRP技术+HSRP技术)讲解+配置
  2. 借款人无需支付利息,Sturdy的无息借贷模式有何特别?
  3. autocad2008许可证错误无法激活的解决办法
  4. python简单登陆QQ邮箱给别人发送邮件
  5. 猴子摘桃问题的C++解决
  6. SpringBoot开发英汉互译网站
  7. 给图片添加下雪的效果
  8. RMAN tablespace point-in-time recovery (TSPITR)
  9. C# 设备终端网络是否能ping通
  10. vue中使用tiff.js展示tif格式的图片