[USACO17DEC]Standing Out from the Herd 广义后缀自动机_DFS

对所有字符串构建一颗广义后缀自动机.

构建过程总,如果转移边已经存在,则说明转移到的字符串在之前出现过,所以该字串的所有字串也都出现过.

那么,就对该点打上标记,对整个后缀树进行一边深度优先搜索.

更新答案即可.

 

 

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 1000000
#define N 30
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int idx[maxn],n,m,ans[maxn]; 
char str[maxn]; 
struct Edge{
    int cnt; 
    int head[maxn], to[maxn], nex[maxn]; 
    void addedge(int u,int v) { nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v; }
    void dfs(int u) {
        for(int i=head[u];i;i=nex[i]) dfs(to[i]);       
        for(int v=head[u];v;v=nex[v]) {
            if(idx[to[v]]==-1){idx[u]=-1;break;}
            if(!idx[to[v]])continue;
            if(!idx[u])idx[u]=idx[to[v]];
            else if(idx[u]!=idx[to[v]]){idx[u]=-1;break;}
        }
    }
}G; 
struct EXSAM{
    int last,tot; 
    int ch[maxn][N],f[maxn],len[maxn]; 
    void init() { last=++tot; }
    void ins(int c,int kth){
        int p=last,np,nq; 
        if(ch[p][c]){           
            int q=ch[p][c];                 
            if(len[q]==len[p]+1) last=q,idx[q]=-1;       
            else {         
                nq=++tot,last=nq; idx[nq]=-1; 
                f[nq]=f[q],f[q]=nq,len[nq]=len[p]+1;  
                memcpy(ch[nq],ch[q],sizeof(ch[q])); 
                while(p&&ch[p][c]==q) idx[p]=-1,ch[p][c]=nq,p=f[p];             
            }
        }       
        else {
            np=++tot,last=np,len[np]=len[p]+1;idx[np]=kth;      
            while(p&&!ch[p][c]) ch[p][c]=np,p=f[p]; 
            if(!p) f[np]=1;
            else {     
                int q=ch[p][c];
                if(len[q]==len[p]+1) f[np]=q;
                else {
                    nq=++tot;
                    f[nq]=f[q],f[q]=f[np]=nq,len[nq]=len[p]+1;
                    memcpy(ch[nq],ch[q],sizeof(ch[q])); 
                    while(p&&ch[p][c]==q) ch[p][c]=nq,p=f[p]; 
                }
            }
        }
    } 
    void Solve() {
        for(int i=2;i<=tot;++i) G.addedge(f[i],i);  
        G.dfs(1);                         
        for(int i=1;i<=tot;++i) {
            int t=idx[i];
            if(t!=-1) ans[t]+=len[i]-len[f[i]]; 
        }
        for(int i=1;i<=n;++i) printf("%d\n",ans[i]); 
    }
}T;
int main(){
    //etIO("input");
    scanf("%d",&n),T.init(); 
    for(int i=1;i<=n;++i) {            
        scanf("%s",str),m=strlen(str),T.last=1;
        for(int j=0;j<m;++j) T.ins(str[j]-'a',i); 
    }
    T.Solve(); 
    return 0;
}

  

posted @ 2019-01-24 15:40  EM-LGH  阅读(217)  评论(0)    收藏  举报