[SPOJ705]不同的子串
Posted 殇雪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SPOJ705]不同的子串相关的知识,希望对你有一定的参考价值。
我们发现这道题可以用后缀自动机做(不会的点这里)
我们发现后缀自动机每条路径代表一条子串,那么我们就DP:
写法一
#include<bits/stdc++.h> #define N 100071 using namespace std; struct Node{ int c[26],fa,val; }T[N]; int tot=1,last=1,D[N],c[N],np,q,nq,len,id[N],ans; char ch[N]; inline void Sam(int x){ np=++tot; T[np].val=T[last].val+1; for (;last&&!T[last].c[x];last=T[last].fa) T[last].c[x]=np; if (!last) T[np].fa=1; else { q=T[last].c[x]; if (T[q].val==T[last].val+1) T[np].fa=q; else { nq=++tot; T[nq]=T[q]; T[nq].val=T[last].val+1; T[np].fa=T[q].fa=nq; for (;last&&T[last].c[x]==q;last=T[last].fa) T[last].c[x]=nq; } } last=np; } int main () { freopen("subst1.in","r",stdin); freopen("subst1.out","w",stdout); scanf("%s",ch+1);len=strlen(ch+1); for (int i=1;i<=len;i++) Sam(ch[i]-\'A\'); for (int i=1;i<=tot;i++) c[T[i].val]++,D[i]=1; for (int i=1;i<=len;i++) c[i]+=c[i-1]; for (int i=1;i<=tot;i++) id[c[T[i].val]--]=i; for (int i=tot;i;i--) for (int j=0;j<26;j++) D[id[i]]+=D[T[id[i]].c[j]]; printf("%d\\n",D[1]-1); // for (int i=tot;i;i--) ans+=T[i].val-T[T[i].fa].val; // printf("%d\\n",ans); return 0; }
我们可以把DP方程化简一下,得到写法二
#include<bits/stdc++.h> #define N 100071 using namespace std; struct Node{ int c[26],fa,val; }T[N]; int tot=1,last=1,D[N],c[N],np,q,nq,len,id[N],ans; char ch[N]; inline void Sam(int x){ np=++tot; T[np].val=T[last].val+1; for (;last&&!T[last].c[x];last=T[last].fa) T[last].c[x]=np; if (!last) T[np].fa=1; else { q=T[last].c[x]; if (T[q].val==T[last].val+1) T[np].fa=q; else { nq=++tot; T[nq]=T[q]; T[nq].val=T[last].val+1; T[np].fa=T[q].fa=nq; for (;last&&T[last].c[x]==q;last=T[last].fa) T[last].c[x]=nq; } } last=np; } int main () { freopen("subst1.in","r",stdin); freopen("subst1.out","w",stdout); scanf("%s",ch+1);len=strlen(ch+1); for (int i=1;i<=len;i++) Sam(ch[i]-\'A\'); // for (int i=1;i<=tot;i++) c[T[i].val]++,D[i]=1; // for (int i=1;i<=len;i++) c[i]+=c[i-1]; // for (int i=1;i<=tot;i++) id[c[T[i].val]--]=i; // for (int i=tot;i;i--) // for (int j=0;j<26;j++) // D[id[i]]+=D[T[id[i]].c[j]]; // printf("%d\\n",D[1]-1); for (int i=tot;i;i--) ans+=T[i].val-T[T[i].fa].val; printf("%d\\n",ans); return 0; }
以上是关于[SPOJ705]不同的子串的主要内容,如果未能解决你的问题,请参考以下文章
SPOJ 705 Distinct Substrings(后缀数组)
SPOJ694&705Distinct Substrings(后缀数组)
SPOJ705-New Distinct Substrings-后缀数组