Question:
The maximum number of words that can be remembered is the sum.
Remember that the previous word is a substring of the word.
Train of Thought Analysis:
First, you must declare that the question is data water before using SA.
The complexity of SA can reach orz (sumlen * sumlen) at most )...
Therefore, the SA processes whether the string is the sub-string of the Next string, and if so, the transfer equation.
DP [I] = max (DP [I], DP [J] + val [I])...
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define maxn 350005#define inf 0x3f3f3f3fusing namespace std;int str[maxn];int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;int bel[maxn];int st[maxn],sumlen[maxn],val[maxn];int dp[maxn];void suffix(int m){ int *x=t1,*y=t2; for(int i=0;i<m;i++)c[i]=0; for(int i=0;i<n;i++)c[x[i]=str[i]]++; for(int i=1;i<m;i++)c[i]+=c[i-1]; for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1) { int p=0; for(int i=n-k;i<n;i++)y[p++]=i; for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(int i=0;i<m;i++)c[i]=0; for(int i=0;i<n;i++)c[x[y[i]]]++; for(int i=0;i<m;i++)c[i]+=c[i-1]; for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; m=p; }}int rank[maxn],height[maxn];void getheight(){ int k=0; for(int i=0;i<n;i++)rank[sa[i]]=i; for(int i=0;i<n;i++) { if(k)k--; if(!rank[i])continue; int j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; }}char tmp[maxn];int main(){ int T,cas=1; for(scanf("%d",&T);T--;) { int N; scanf("%d",&N); n=0; for(int i=1;i<=N;i++) { scanf("%s%d",tmp,&val[i]); dp[i]=val[i]; int len=strlen(tmp); st[i]=n; sumlen[i]=len; for(int j=0;j<len;j++) { str[n]=tmp[j]; bel[n++]=i; } bel[n]=i; str[n++]=i+128; } str[n-1]=0; suffix(30000); getheight(); for(int i=1;i<=N;i++) { int mlen=inf; for(int j=rank[st[i]]+1;j<n;j++) { mlen=min(mlen,height[j]); if(mlen<sumlen[i])break; if(bel[sa[j]]>i) { dp[bel[sa[j]]]=max(dp[bel[sa[j]]],val[bel[sa[j]]]+dp[i]); } } mlen=inf; for(int j=rank[st[i]]-1;j>0;j--) { mlen=min(mlen,height[j+1]); if(mlen<sumlen[i])break; if(bel[sa[j]]>i) { dp[bel[sa[j]]]=max(dp[bel[sa[j]]],val[bel[sa[j]]]+dp[i]); } } } printf("Case #%d: %d\n",cas++,max(0,*max_element(dp+1,dp+1+N))); } return 0;}/*16abbab 800a 1ab 2abb 3baba 5abbab 8*/
HDU 4117 GRE words (suffix array + dp)