The main idea: given the sum of n lengths of not more than 10W of string, to find a shortest number of strings, so that the sum of the occurrences of all the string =m this n string guarantees do not contain each other
TM, can you translate it well?
F[I][J] Indicates how much length will be added after the first string followed by the first J string
Since J must not be a substring of I, this is actually the longest suffix of I, which is also the prefix of J
Note that you cannot connect an edge with a length of 0, so ensure that this length is <len[i when I=j]
How can I ask for it? In fact, a hash, enumeration I and j, violence can be done
It's not a T?
First set the length of the string I is AI, set K=σai
Easy to know when calculating f[i][j] The complexity is O (min (ai,aj))
So the problem now is that when K is fixed, maximize σσmin (Ai,aj)
We sequence all the AI, and it's easy to see that when the next two numbers AI and AJ both become (AI+AJ)/2, the target function will definitely grow.
Prove:
If Ak<=ai<aj, then min (ak,ai) and Min (Ak,aj) will not change
If Ai<aj<=ak, then min (ai,ak) +min (Aj,ak) =ai+aj must be the same
Min (Ai,ai) +min (Aj,aj) =ai+aj also unchanged
Only min (Ai,aj) has increased
So eventually when all the AI are the same target function maximum
So each AI equals k/n, the final time complexity of this step is O (k/n*n^2) =o (kn)
K=10w,n=200, obviously not t
The problem now is that given a graph, the shortest path to the M-edge is obtained from the source point.
Multiply Floyd can
Final time complexity O (KN+N^3LOGN)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 220# Define BASE 131#define MOD 999911657using namespace Std;int n,m,len[m];char Str[101000],*s[m];long long power[101000],_ Hash[101000],*hash[m];long Long F[m][m],g[m][m],ans[m][m];int Get_hash (Long long *hash,int l,int r) {int len=r-l+1; Return (Hash[r]-hash[l-1]*power[len]%mod+mod)%mod;} int Calculate (int x,int y)//calculates x's longest suffix, which is also the prefix of y {int i;for (i=min (Len[x],len[y])-(len[y]<=len[x]), ~i;i--) if (get_ Hash (hash[x],len[x]-i,len[x]-1) = = Get_hash (hash[y],0,i-1)) return I;return 0;} int main () {int t,i,j,k;cin>>n>>m;int temp=1,max_len=0;for (i=1;i<=n;i++) {scanf ("%s", str+temp); s[i]= Str+temp;hash[i]=_hash+temp;len[i]=strlen (S[i]); Max_len=max (Max_len,len[i]); ++temp+=len[i];for (J=0;j<len[i] ; j + +) hash[i][j]= (hash[i][j-1]*base+s[i][j])%mod;} for (power[0]=1,i=1;i<=max_len;i++) Power[i]=power[i-1]*base%mod;memset (f,0x3f,sizeof f), for (i=1;i<=n;i++) { F[0][i]=len[i];for (j=1;j<=n;j++) f[i][j]=len[j]-calculate (i,j);} Memset (ans,0x3f,sizeof ans); for (i=1;i<=n;i++) ans[i][i]=0;for (t=0; (1<<t) <=m; t++) {if (T) {memset (g,0x3f,sizeof g); for (k=0;k<=n;k++) for (i=0;i<=n;i++) for (j=0;j<=n;j++) g[i][j]=min (G[i] [J],f[i][k]+f[k][j]); memcpy (f,g,sizeof f);} if (m& (1<<t)) {memset (g,0x3f,sizeof g); for (k=0;k<=n;k++) for (i=0;i<=n;i++) for (j=0;j<=n;j++) G[i] [J]=min (G[i][j],f[i][k]+ans[k][j]); memcpy (ans,g,sizeof ans);}} Long Long ans=0x3f3f3f3f3f3f3f3fll;for (i=1;i<=n;i++) ans=min (Ans,::ans[0][i]);cout<<ans<<endl; return 0;}
Bzoj 2085 Poi2010 Hamsters hash+ multiplier Floyd