zoukankan      html  css  js  c++  java
  • trie树上的回文自动机

    因为本人菜的原因,看本博客可能不如直接看论文

    这个应该算pam最基础的扩展了。例题可以看hdu5394

    直接暴力插入的复杂度肯定是不对的,是n^2的,我们需要优化找fail那个函数。

    也就是说,我们要优化这样的操作,对于pam上的一个节点x,找到最长的前驱为c的回文后缀。

    特判第一步就找到的情况。否则这个前驱字符一定在x内,可以预处理。每次新插入的点继承他fail的数组。

    更具体的细节可以看代码。(也没有细节了)

    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<climits>
    #include<ctime>
    #include<iostream>
    #include<vector>
    #include<cassert>
    #include<algorithm>
    #include<utility>
    #include<queue>
    #pragma comment(linker,"/STACK:102400000,102400000")
    using namespace std;
    #define forg(i,x) for(register int i=fir[x];i;i=nxt[i])
    #define uu unsigned
    #define scanf a14=scanf
    #define rint register int
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
    typedef long long ll;
    typedef uu long long ull;
    typedef pair<int,int> pii;
    int a14;
    inline int rd(int l,int r){return rand()%(r-l+1)+l;}
    
    const int mxn=2e6+5;
    int len[mxn],fail[mxn],ts[mxn][4],tt,po[mxn],n,co[mxn],cnt[mxn],ju[mxn][4];
    vector<int>g[mxn];
    int s[mxn];
    
    inline int gf(int x,int i){if(s[i]==s[i-len[x]-1])return x; return ju[x][s[i]];}
    inline int ext(int id,int c,int n){
        int x=gf(id,n);
        if(!ts[x][c]){
            ++tt,len[tt]=len[x]+2;
            int y=ts[gf(fail[x],n)][c];if(!y)y=1;
            fail[tt]=y;
            ju[tt][0]=ju[y][0],ju[tt][1]=ju[y][1],ju[tt][2]=ju[y][2],ju[tt][3]=ju[y][3]; 
            ju[tt][s[n-len[y]]]=y;
            ts[x][c]=tt;
        }
        return ts[x][c];
    }
    
    inline void dfs(int x=0,int f=0,int d=0){
        if(x)s[d]=co[x]-'a',po[x]=ext(po[f],s[d],d),++cnt[po[x]];
        for(int i=0;i<g[x].size();++i)dfs(g[x][i],x,d+1);
    }
    int main(){
        s[0]=666;
        int ca;scanf("%d",&ca);while(ca--){
            for(int i=0;i<=tt;++i)ts[i][0]=ts[i][1]=ts[i][2]=ts[i][3]=cnt[i]=0;
            for(int i=0;i<=n;++i)g[i].clear();
    //        len[1]=-1,tt=1,fail[0]=fail[1]=1;
            len[0]=-1,tt=1;
            scanf("%d",&n);for(int i=1;i<=n;++i){
                char c[2];int x;scanf("%s%d",c,&x);co[i]=c[0];
                g[x].push_back(i);
            }
            dfs();
            ll ans=0;
            for(int i=tt;i>1;--i)cnt[fail[i]]+=cnt[i],ans+=1ll*cnt[i]*len[i];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    前缀判断 蓝桥杯
    dedecms 网站内容静态化和动态化的切换
    dedecms 频道标签 channel.lib.php的分析
    JavaScript通过闭包解决只能取得包含函数中任何变量最后一个值的问题
    JavaScript闭包 取for循环i 【转】
    JavaScript装饰模式
    JavaScript闭包意义谈
    JavaScriptjs闭包测试
    JavaScript闭包的作用谈(转)
    Zend Engine 简介
  • 原文地址:https://www.cnblogs.com/happyguy/p/14690733.html
Copyright © 2011-2022 走看看