Po姐的题解:http://blog.csdn.net/popoqqq/article/details/44077515
搬运下复杂度分析吧
这不会T?
首先设第i个字符串的长度为ai,设k=Σai
易知当计算f[i][j]时的复杂度是O(min(ai,aj))
那么现在的问题就是当k固定时,最大化ΣΣmin(ai,aj)
我们将所有的ai排个序,容易发现当相邻的两个数ai和aj都变为(ai+aj)/2时目标函数一定会增大
证明:
若ak<=ai<aj,那么min(ak,ai)和min(ak,aj)都不变
若ai<aj<=ak,那么min(ai,ak)+min(aj,ak)=ai+aj一定不变
min(ai,ai)+min(aj,aj)=ai+aj也不变
只有min(ai,aj)增大了
因此最终当所有的ai都相同时目标函数最大
故每个ai都等于k/n,这一步的最终时间复杂度是O(k/n*n^2)=O(kn)
k=10W,n=200,显然不会T
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline int read(char *s) { char c=nc();int len=0; for (;!(c>='a' && c<='z');c=nc()); for (;c>='a' && c<='z';s[++len]=c,c=nc()); s[++len]=0; return len-1; } const int N=205; ll f[N][N],h[N][N],tmp[N][N]; ll ans=1LL<<60; int Len,n,m; char S[200005],str[200005]; int st[N],ed[N],len[N]; const ll P=1000000007,X=1234567; ll H[200005],iX[200005]; inline void Pre() { iX[0]=1; for (int i=1;i<=Len;i++) (iX[i]=iX[i-1]*X)%=P; for (int i=Len;i;i--) (H[i]=H[i+1]*X+S[i]-'a')%=P; } inline ll Get(int l,int r){ return ((H[l]-H[r+1]*iX[r-l+1])%P+P)%P; } inline ll Get(int x,int l,int r){ return Get(st[x]+l-1,st[x]+r-1); } inline int Calc(int x,int y){ for (int i=min(len[x],len[y])-(len[y]<=len[x]);~i;i--) if (Get(x,len[x]-i+1,len[x])==Get(y,1,i)) return len[y]-i; return len[y]; } int main() { freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); m--; for (int i=1;i<=n;i++) { len[i]=read(str); st[i]=ed[i-1]+1; ed[i]=st[i]+len[i]-1; for (int j=1;j<=len[i];j++) S[++Len]=str[j]; } Pre(); memset(f,0x3f,sizeof(f)); memset(h,0x3f,sizeof(h)); for (int i=1;i<=n;i++) h[i][i]=0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) f[i][j]=Calc(i,j); for (int t=0;(1<<t)<=m;t++) { if (m&(1<<t)) { memset(tmp,0x3f,sizeof(tmp)); for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) tmp[i][j]=min(tmp[i][j],h[i][k]+f[k][j]); memcpy(h,tmp,sizeof(tmp)); } memset(tmp,0x3f,sizeof(tmp)); for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) tmp[i][j]=min(tmp[i][j],f[i][k]+f[k][j]); memcpy(f,tmp,sizeof(tmp)); } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) ans=min(ans,len[i]+h[i][j]); printf("%lld\n",ans); return 0; }