后缀自动姬好,好写好调好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 }