[BZOJ4199][Noi2015]品酒大会 树形DP+后缀自动机
由于要找后缀的前缀,所以先用反串建立SAM。
link边组成了后缀树。
两个子串的最长公共前缀是LCA的step
树形dp即可。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define maxn 1200000 8 using namespace std; 9 struct edge { 10 int to,next; 11 }e[maxn]; 12 int n,a[maxn]; 13 char s[maxn]; 14 int head[maxn],d; 15 long long ans[maxn],mx[maxn],mn[maxn],sum[maxn]; 16 struct data { 17 int last,cnt; 18 int son[maxn][26],link[maxn],step[maxn],v[maxn],size[maxn]; 19 int tmp[maxn]; 20 data() {last=cnt=1;v[1]=2147483647;} 21 void extend(int c,int val) { 22 int p=last,np=last=++cnt;step[np]=step[p]+1;v[np]=val,size[np]=1; 23 while(p&&!son[p][c]) son[p][c]=np,p=link[p]; 24 if(!p) link[np]=1; 25 else { 26 int q=son[p][c]; 27 if(step[q]==step[p]+1) link[np]=q; 28 else { 29 int nq=++cnt;v[nq]=2147483647; 30 memcpy(son[nq],son[q],sizeof(son[q])); 31 link[nq]=link[q]; 32 link[q]=link[np]=nq; 33 step[nq]=step[p]+1; 34 while(son[p][c]==q&&p) son[p][c]=nq,p=link[p]; 35 } 36 } 37 } 38 void add(int u,int v) {e[d].next=head[u];e[d].to=v;head[u]=d++;} 39 void build() {for(int i=1;i<=cnt;i++) add(link[i],i),ans[i]=-21474836470000000000000LL;} 40 void query(int x) { 41 mx[x]=-2147483647;mn[x]=2147483647; 42 if(v[x]!=2147483647) mx[x]=mn[x]=v[x]; 43 for(int i=head[x];i>=0;i=e[i].next) { 44 int to=e[i].to; 45 query(to); 46 if(mx[x]!=-2147483647&&mn[x]!=2147483647&&mx[to]!=-2147483647&&mn[to]!=2147483647) ans[step[x]]=max(ans[step[x]],max(mx[x]*mx[to],mn[to]*mn[x])); 47 mx[x]=max(mx[x],mx[to]);mn[x]=min(mn[x],mn[to]); 48 sum[step[x]]+=1LL*size[x]*size[to];size[x]+=size[to]; 49 } 50 51 } 52 void getans() { 53 for(int i=n-1;i>=0;i--) sum[i]+=sum[i+1],ans[i]=max(ans[i],ans[i+1]); 54 for(int i=0;i<=n-1;i++) if(sum[i]) printf("%lld %lld\n",sum[i],ans[i]); else printf("0 0\n"); 55 } 56 57 }sam; 58 59 int main() { 60 memset(head,-1,sizeof(head)); 61 scanf("%d",&n); 62 scanf("%s",s+1); 63 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 64 for(int i=n;i>=1;i--) sam.extend(s[i]-'a',a[i]); 65 sam.build(); 66 sam.query(1); 67 sam.getans(); 68 69 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~