首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【BZOJ4566】【HAOI2016】找相同字符

后缀自动姬好,好写好调好ac

原题:

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。
1 <=n1, n2<= 20000
 
之前写了个后缀数组+并查集的,因为我只会后缀数组……
后看看dalao们纷纷使用后缀自动姬秒题,决定提高一下自己姿势水平,学一发后缀自动姬
然后根本无法理解啊quq,现在板子差不多理解了,但是自动姬上做DP的延伸还是不能理解quq
多做题应该就能理解了吧……
这题dp具体思路是啥我也没搞懂,直接上结论
每个点的贡献:|right(x)|*(max[x]-max[fa[x]])
具体贡献到答案上,就搞一个b在当前节点上匹配的公共长度l,然后对答案的贡献就是|right(x)|*(l-max[fa[x]])
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 int rd(){int z=0,mk=1;  char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
11     return z*mk;
12 }
13 char a[210000],b[210000];  int n,m;
14 int nxt[810000][26],fa[810000],mx[810000],sz[810000];
15 int lst=1,tt=1;
16 int cnt[810000],cntrk[810000];
17 ll f[810000];
18 void ist(int x){
19     int p=lst,np=lst=++tt;
20     mx[np]=mx[p]+1;  sz[np]=1;
21     while(!nxt[p][x] && p)  nxt[p][x]=np,p=fa[p];
22     if(!p)  fa[np]=1;
23     else{
24         int q=nxt[p][x];
25         if(mx[p]+1==mx[q])  fa[np]=q;
26         else{
27             int nq=++tt;  mx[nq]=mx[p]+1;
28             memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
29             fa[nq]=fa[q],fa[q]=fa[np]=nq;
30             while(nxt[p][x]==q)  nxt[p][x]=nq,p=fa[p];
31         }
32     }
33 }
34 void gtcntrk(){
35     for(int i=1;i<=tt;++i)  ++cnt[mx[i]];
36     for(int i=1;i<=n;++i)  cnt[i]+=cnt[i-1];
37     for(int i=tt;i;--i)  cntrk[cnt[mx[i]]--]=i;
38 }
39 void gtf(){
40     for(int i=tt;i;--i)  sz[fa[cntrk[i]]]+=sz[cntrk[i]];
41     for(int i=1;i<=tt;++i)
42         f[cntrk[i]]=f[fa[cntrk[i]]]+(ll)sz[cntrk[i]]*(mx[cntrk[i]]-mx[fa[cntrk[i]]]);
43 }
44 int main(){//freopen("ddd.in","r",stdin);
45     scanf("%s%s",a+1,b+1);  n=strlen(a+1),m=strlen(b+1);
46     for(int i=1;i<=n;++i)  ist(a[i]-'a');
47     gtcntrk(),gtf();
48     ll bwl=0;  int l=0,tmp=1,x;
49     for(int i=1;i<=m;++i){
50         x=b[i]-'a';
51         if(nxt[tmp][x])  tmp=nxt[tmp][x],++l;
52         else{
53             while(!nxt[tmp][x] && tmp)  tmp=fa[tmp];
54             if(!tmp)  tmp=1,l=0;
55             else  l=mx[tmp]+1,tmp=nxt[tmp][x];
56         }
57         if(tmp!=1)  bwl+=f[fa[tmp]]+(ll)sz[tmp]*(l-mx[fa[tmp]]);
58     }
59     cout<<bwl<<endl;
60     return 0;
61 }
View Code

 

posted on 2017-03-13 20:26  cdcq_old  阅读(448)  评论(0编辑  收藏  举报