字符串hash+回文树——hdu6599

拖了很久才补的回文树,感觉网上的博客都是一个做法。。回文树统计不同种类的回文串出现次数,然后用字符串hash来判每个回文子串是否符合要求

#include<bits/stdc++.h>
using namespace std;
#define maxn 300005
#define mod 19260817
#define ll long long
#define P 131
char s[maxn];
ll len,F[maxn],h[maxn];

ll has(int l,int r){
    return (h[r]-h[l-1]*F[r-l+1]%mod+mod)%mod;
}

struct PAM{
    int nxt[maxn][26],fail[maxn];
    int len[maxn],S[maxn];
    int cnt[maxn],num[maxn];
    int n,p,last,id[maxn];//记录第i个结点的后缀下标
    int newnode(int l){
        memset(nxt[p],0,sizeof nxt[p]);
        len[p]=l;
        cnt[p]=num[p]=0;
        return p++;
    } 
    void init(){
        memset(cnt,0,sizeof cnt);
        memset(num,0,sizeof num);
        p=0;
        newnode(0);
        newnode(-1);
        last=n=0;
        S[0]=-1; 
        fail[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]++;
        id[last]=n;
    }
    ll ans[maxn];
    ll count(){
        memset(ans,0,sizeof ans);
        for(int i=p-1;i>=0;i--)cnt[fail[i]]+=cnt[i];
        
        for(int i=2;i<p;i++){
            int L=id[i]-len[i],R=id[i]-1;
            int mid=(L+R)/2; 
            ll tmp1=has(L,mid)%mod;
            ll tmp2;
            if(len[i]%2==0)
                tmp2=has(mid+1,R)%mod;
            else tmp2=has(mid,R)%mod;
            if(tmp1==tmp2)
                ans[len[i]]+=cnt[i];
        }
    }
}tr;
int main(){
    F[0]=1;
    for(int i=1;i<=300000;i++)F[i]=F[i-1]*P%mod;
    
    while(scanf("%s",&s)!=EOF){
        tr.init();
        len=strlen(s);
        for(int i=0;i<len;i++)
            tr.add(s[i]);
        
        h[0]=s[0];
        for(int i=1;i<len;i++)
            h[i]=(h[i-1]*P%mod+s[i])%mod;
        tr.count();
        
        for(int i=1;i<len;i++)
            cout<<tr.ans[i]<<" ";
        cout<<tr.ans[len]<<'
';
    }
}
原文地址:https://www.cnblogs.com/zsben991126/p/11328137.html