[BZOJ 2085]POI2010 Hamsters

来源:互联网 发布:成绩管理系统c语言 编辑:程序博客网 时间:2024/05/16 02:22

表示蒟蒻在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;}



0 0