表示蒟蒻在ac这道题之前理解的矩乘都是极为片面的
原本我以为矩乘只能优化线性转移,例如f[n]=ai*f[i]+aj*f[j]+ak*f[k].......
其实这样的方程也是可以转移的:f[n]=min(f[i]+ai,f[j]+aj,f[k]+ak......)
Matrix operator *(const Matrix &x)const{
Matrix ret;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
ret.a[i][j]=100000000;
ret.a[i][j]*=ret.a[i][j];
for (int k=1;k<=n;k++)
ret.a[i][j]=min(ret.a[i][j],a[i][k]+x.a[k][j]);
}
return ret;
}
再吐槽一下巴中的翻译吧。以下是其翻译漏的一句话
“ You can assume that no hamster's name occurs (as a contiguous fragment) in any other hamster's name. ”
(保证名字互不包含)
这是矩乘的前提保证,翻译太有良心了。。。(在这边被卡了好久。。。)
老样子,代码比较慢比较丑
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int Maxn=100005;
char C[Maxn],S[Maxn],ch;
int next[Maxn],a[Maxn],len[205],q[Maxn],fl[Maxn];
int num[205],Dis[Maxn],n,m,l,r,i,j,k,tot;
LL ans;
struct Matrix
{
LL a[205][205];
Matrix operator *(const Matrix &x)const{
Matrix ret;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
ret.a[i][j]=100000000;
ret.a[i][j]*=ret.a[i][j];
for (int k=1;k<=n;k++)
ret.a[i][j]=min(ret.a[i][j],a[i][k]+x.a[k][j]);
}
return ret;
}
} A, B;
void add(int x,char ch){ C[++tot]=ch; next[tot]=a[x]; a[x]=tot; }
int Judge(int x,char ch){
for (int i=a[x];i;i=next[i])
if (ch==C[i]) return i;
return 0;
}
void ins(int x){
scanf("%s",S);
len[x]=strlen(S);
int i,j;
for (i=0,j=0;i<len[x];i++)
if (Judge(j,S[i])) j=Judge(j,S[i]);
else add(j,S[i]), j=tot;
num[x]=j;
for (i=0;i<len[x];i++) fl[i]=-1;
for (i=1,j=-1;i<len[x];i++){
while (j>=0 && S[j+1]!=S[i]) j=fl[j];
if (S[j+1]==S[i]) j++;
fl[i]=j;
}
A.a[x][x]=len[x]-j-1;
}
void AC_Auto(){
for (q[l=r=1]=0;l<=r;l++){
for (i=a[q[l]];i;i=next[i]) q[++r]=i;
if (q[l]==0) continue;
for (i=a[q[l]];i;i=next[i]){
int x=fl[q[l]];
while (x!=0 && !Judge(x,C[i])) x=fl[x];
fl[i]=Judge(x,C[i]);
}
}
for (i=1;i<=n;i++){
memset(Dis,127/2,sizeof(Dis));
for (j=num[i],r=0;j>0;j=fl[j])
Dis[q[++r]=j]=0;
Dis[q[++r]=0]=0;
for (l=1;l<=r;l++){
for (j=a[q[l]];j;j=next[j])
for (k=j;k>0;k=fl[k])
if (Dis[k]<=Dis[q[l]]+1) break;
else Dis[q[++r]=k] = Dis[q[l]]+1;
}
for (j=1;j<=n;j++)
if (i!=j) A.a[i][j]=Dis[num[j]];
}
}
void qck(int q){
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (i!=j) B.a[i][j]=ans;
else B.a[i][j]=len[i];
for (;q>0;q>>=1){
if (q&1) B=B*A;
A = A * A;
}
}
int main(){
freopen("cho.in","r",stdin);
freopen("cho.out","w",stdout);
scanf("%d%d\n",&n,&m);
memset(A.a,100,sizeof(A.a));
for (i=1;i<=n;i++) ins(i);
AC_Auto();
ans=1000000000;
ans=ans*ans;
qck(m-1);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
ans=min(ans,B.a[i][j]);
printf("%If4d\n",ans);
return 0;
}