[Codeforces][后缀自动机]Helvetic Coding Contest 2017 . I Fake News (hard)

来源:互联网 发布:广告联盟js代码 编辑:程序博客网 时间:2024/05/19 07:08

一看是字符串题,就想一想怎么在后缀自动机上搞

有一个跟BZOJ3238 差异差不多的思路,建出原串反串的后缀自动机,那么每个子串的lcp就是对应节点的lca,那么lcp出现次数就是这个节点的right集合,拷了拷之前的代码,改一改就过了……

#include <cstdio>#include <iostream>#include <cstring>#include <string>#define N 500010<<1using namespace std;typedef long long ll;struct SAM_{    int next[N][26],fail[N],stp[N],p,cnt,t[N],r[N];    ll f[N],w[N];    SAM_(){p=cnt=1;}    void clear(){        p=cnt=1;        memset(next,0,sizeof(next));        memset(fail,0,sizeof(fail));        memset(stp,0,sizeof(stp));        memset(t,0,sizeof(t));        memset(r,0,sizeof(r));        memset(f,0,sizeof(f));        memset(w,0,sizeof(w));        }    void Extend(int x){        x-='a';        int np=++cnt;stp[np]=stp[p]+1;w[np]=f[np]=1;        while(p&&!next[p][x]) next[p][x]=np,p=fail[p];        if(!p) fail[np]=1;        else{            int q=next[p][x];            if(stp[q]==stp[p]+1) fail[np]=q;            else{                int nq=++cnt;stp[nq]=stp[p]+1;                memcpy(next[nq],next[q],sizeof(next[q]));                fail[nq]=fail[q];                fail[q]=fail[np]=nq;                while(p&&next[p][x]==q) next[p][x]=nq,p=fail[p];            }        }        p=np;    }    void Samort(){        int i;        for(i=0;i<=cnt;i++) t[i]=0;        for(i=1;i<=cnt;i++) t[stp[i]]++;        for(i=1;i<=cnt;i++) t[i]+=t[i-1];        for(i=1;i<=cnt;i++) r[t[stp[i]]--]=i;    }    void Solve(int n){        for(int i=cnt;i;i--)f[fail[r[i]]]+=f[r[i]];        ll Ans=0;        for(int i=2;i<=cnt;i++)                    Ans+=1LL*(stp[i]-stp[fail[i]])*f[i]*f[i];        printf("%lld\n",Ans);    }}SAM;char A[N];int n;int main(){    int t;    scanf("%d",&t);    while(t--){        SAM.clear();        scanf("%s",A+1);n=strlen(A+1);    for(int i=n;i;i--)      SAM.Extend(A[i]);    SAM.Samort();    SAM.Solve(n);    }}
原创粉丝点击