zoukankan      html  css  js  c++  java
  • 字符串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]<<'
    ';
        }
    }
  • 相关阅读:
    anaconda安装TensorFlow
    复习NLP-实战(三)
    复习NLP-实战(二)
    复习NLP-实战(一)
    python爬虫实战
    WebSocket实战(一)
    不上传图片直接本地预览
    oracle导出
    使用正则表达式验证学习成绩分数
    限制文本框,文本域输入的字符数量
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11328137.html
Copyright © 2011-2022 走看看