Palindrome tree dfs-- cattle off more school sixth C

/ * 
SET must be different in the nature of a palindromic sequence, we first establish palindromic tree 
when a pointer can be reached by nxt b, or b can be reached via a pointer fail, b is a substring 
for tree palindromic each node u, and we can be related to its junction into two parts: 
    1. the junction point below subtree, all nodes that can be obtained by a part of the u in dotted sides, set size size [u ] 
    2. node upwardly chain fail, all the nodes on this chain are palindromes suffix u, set size TOT [u] 
substring fail then all points on the chain are u subtree, so u contributions to the size [u] * tot [u ] 
and then have to go heavy: for the sons of v u, v of the chain may fail coincide with u, u contribution part coincide Department has calculated that, then clearly v the operator will not need a 
so use vis dfs fail mark points are visited, before the launch of recursive backtracking to 
 * / 
#include <bits / STDC ++ H.>
 the using  namespace STD;
 #define MAXN 100005
 struct the PAM {
     int NXT [MAXN] [ 26 is ], len [MAXN], Fail [MAXN];
     int NUM [MAXN], CNT [MAXN];
     int S[maxn],n,p,last;
    int newnode(int l){
        memset(nxt[p],0,sizeof nxt[p]);
        len[p]=l;
        num[p]=cnt[p]=0;
        return p++;
    }
    void init(){
        p=0;
        newnode(0);
        newnode(-1);
        fail[0]=1;
        last=n=0;
        S[0]=-1;
    }
    int get_fail(int x){
        while(S[n-len[x]-1]!=S[n])x=fail[x];
        return x;
    }
    void add(int c){
        c-='a';S[++n]=c;
        int cur=get_fail(last);
        if(!nxt[cur][c]){
            int now=newnode(len[cur]+2);
            fail[now]=nxt[get_fail(fail[cur])][c];
            nxt[cur][c]=now;
            num[now]=num[fail[now]]+1;
        }
        last=nxt[cur][c];
        cnt[last]++;
    }
    int vis[maxn],size[maxn],tot[maxn];
    void dfs1(int u){
        size[u]=1;
        for(int i=0;i<26;i++)
            if(nxt[u][i]){
                int v=nxt[u][i];
                dfs1(v);
                size[u]+=size[v];
            }
    }
    void dfs2(int u){
        tot[u]=0;
        for(int x=u;!vis[x] && x>1;x=fail[x])
            tot[u]++,vis[x]=u;
        for(int i=0;i<26;i++)
            if(nxt[u][i]){
                int v=nxt[u][i];
                dfs2(v);
            }
        for(int x=u;vis[x]==u&&x>1;x=fail[x])    
            vis[x]=0;
    }
    long long count(){
        for(int i=p-1;i>=2;i--)
            cnt[fail[i]]+=cnt[i];
        dfs1(0);dfs2(0);
        dfs1(1);dfs2(1);
        long long res=0;
        for(int i=2;i<p;i++)
            res=res+size[i]*tot[i];
        return res-(p-2);    
    }
}tr; 
char s[maxn];

int main(){
    int t;cin>>t;
    for(int tt=1;tt<=t;tt++){
        scanf("%s",s);
        int len=strlen(s);
        tr.init();
        for(int i=0;i<len;i++)
            tr.add(s[i]);
        printf("Case #%d: %lld\n",tt,tr.count());
    } 
} 

 

Guess you like

Origin www.cnblogs.com/zsben991126/p/11329261.html