因为字符串互不包含,所以求出从每一个字符串跑到另一个字符串最少要多少个字符,然后倍增floyd即可
求从一个字符串到另一个字符串要多少字符就是第一个字符串最长多少的后缀与第二个字符串的前缀相等,暴力即可,易知当长度都相等的时候复杂度最高,为n*sigma len
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 210
#define MAXM 100010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
#define bas 233
int n;
struct mat{
ll f[MAXN][MAXN];
mat(){
memset(f,0x3f,sizeof(f));
}
friend mat operator *(mat x,mat y){
int i,j,k;
mat z;
for(k=0;k<=n;k++){
for(i=0;i<=n;i++){
for(j=0;j<=n;j++){
z.f[i][j]=min(z.f[i][j],x.f[i][k]+y.f[k][j]);
}
}
}
return z;
}
};
int m;
char s[MAXM];
int len[MAXN];
vector<ll>h[MAXN];
mat x,y;
ll ans=1e18;
ll mi[MAXM];
ll get(int x,int l,int r){
return (h[x][r]-h[x][l-1]*mi[r-l+1]%MOD+MOD)%MOD;
}
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%s",s+1);
len[i]=strlen(s+1);
ll now=0;
h[i].push_back(0);
for(j=1;j<=len[i];j++){
now=(now*bas+s[j])%MOD;
h[i].push_back(now);
}
}
mi[0]=1;
for(i=1;i<MAXM;i++){
mi[i]=mi[i-1]*bas%MOD;
}
y.f[0][0]=0;
for(i=1;i<=n;i++){
x.f[0][i]=len[i];
y.f[i][i]=0;
for(j=1;j<=n;j++){
int L=0;
for(k=1;k<len[i]&&k<len[j];k++){
if(get(i,len[i]-k+1,len[i])==get(j,1,k)){
L=k;
}
}
x.f[i][j]=len[j]-L;
}
}
while(m){
if(m&1){
y=y*x;
}
x=x*x;
m>>=1;
}
for(i=1;i<=n;i++){
ans=min(ans,y.f[0][i]);
}
printf("%lld\n",ans);
return 0;
}
/*
5
1000000000
ab
bc
cd
de
ea
*/