zoukankan      html  css  js  c++  java
  • 双倍快乐(回文树)

    Zweib很喜欢回文串,每当看见回文串,他就会觉得很快乐。当且仅当字符串z首位倒置后仍然与原来的串z完全相同时,z 被称为回文串,例如 abcba,abba,a是回文串,而 ab,abcca不是回文串。

    这一天Zweib突发奇想,如果用有一个字符串 t是由2个非空的回文串 x 和 y 组成的(,>0),不就可以获得双倍的快乐了吗(迫真突发奇想),于是他想从一个给定的字符串 s 中找出一个子串 t 满足 t 由2个回文串组成,但是他不知道自己能取到的 t 最长为多少,你能帮帮他吗?

    ps:当 t 满足 t 是 s 中一串连续的字符组成的字符串时,t 被称为 s 的子串。显然 s 本身也是自己的子串。

    题解:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    const int maxn=3e5+100;
    int a[maxn];
    ll f[maxn];
    ll p[maxn];
    ll cal (int l,int r) {
        if (l==0) return f[r];
        return f[r]-f[l-1]*p[r-l+1];
    }
    bool check (int l,int r) {
        int mid=(l+r)>>1;
        if ((r-l+1)&1)
            return cal(l,mid)==cal(mid,r);
        else
            return cal(l,mid)==cal(mid+1,r);
        //分别判断
    }
    int Hash[maxn];//表示起点为i的回文串的最大长度
    struct palin_Tree {
        //回文树
        int nxt[maxn][26];
        int fail[maxn];
        int len[maxn];
        int cnt[maxn];
        int S[maxn];
        int ind[maxn];
        int last,id,n;
        /*
         * 一个节点表示一个本质不同的回文串
         * len[i]表示回文串i的长度
         * nxt[i][c]表示编号为i的节点表示的回文串在两边添加字符c以后变成的回文串的编号
         * cnt[i]表示节点i表示的本质不同的串的个数
         * fail[i]表示节点i失配以后跳转不等于自身的节点i表示的回文串的最长后缀回文串
         * last表示新添加一个字母后形成的最长回文串表示的节点
         * S[i]表示第i次添加的字符
         * ind[i]表示第i号节点是插入到第ind[i]号字符串产生的节点
         */
        int newNode (int x) {
            for (int i=0;i<26;i++)
                nxt[id][i]=0;
            cnt[id]=0;
            len[id]=x;
            return id++;
        }
        void init () {
            id=0;
            newNode(0);
            newNode(-1);
            fail[0]=1;
            S[0]=-1;
            last=n=0;
        }
        int getfail (int x) {
            while (S[n-len[x]-1]!=S[n]) x=fail[x];
            return x;
        }
        void insert (int c) {
            c-='a';
            S[++n]=c;
            int cur=getfail(last);
            if (!nxt[cur][c]) {
                int u=newNode(len[cur]+2);
                fail[u]=nxt[getfail(fail[cur])][c];
                nxt[cur][c]=u;
            }
            last=nxt[cur][c];
            cnt[last]++;
            ind[last]=n;
        }
        int getMax () {
            int Max=0;
            for (int i=id-1;i>=0;i--) cnt[fail[i]]+=cnt[i];
            for (int i=0;i<id;i++)
                //if (check(ind[i]-len[i],ind[i]-1))
                //   a[len[i]]+=cnt[i]
                    Hash[ind[i]-len[i]]=max(Hash[ind[i]-len[i]],len[i]);
            for (int i=id-1;i>=0;i--)
                if (len[i]>=0&&Hash[ind[i]]) Max=max(Max,len[i]+Hash[ind[i]]);
            return Max;
        }
    }Palin_Tree;
    char s[maxn];
    int main () {
        p[0]=1;
        for (int i=1;i<maxn;i++) p[i]=p[i-1]*13331;
        while (~scanf("%s",s)) {
            int ans=0;
            memset(Hash,0,sizeof(Hash));
            int len=strlen(s);
            for (int i=0;i<=len;i++) a[i]=0;
            Palin_Tree.init();
            for (int i=0;i<len;i++) Palin_Tree.insert(s[i]);
            f[0]=s[0];
            for (int i=1;i<len;i++)
                f[i]=f[i-1]*13331+s[i];
            ans=max(ans,Palin_Tree.getMax());
    
            memset(Hash,0,sizeof(Hash));
            len=strlen(s);
            for (int i=0;i<=len;i++) a[i]=0;
            Palin_Tree.init();
            for (int i=len-1;i>=0;i--) Palin_Tree.insert(s[i]);
            f[0]=s[0];
            for (int i=1;i<len;i++)
                f[i]=f[i-1]*13331+s[i];
            ans=max(ans,Palin_Tree.getMax());
            cout<<ans<<"
    ";
        }
    }
  • 相关阅读:
    hdu 5965 扫雷
    51nod 1441 士兵的数字游戏 (素数处理
    51nod 1453抽彩球
    51nod 1255 字典序最小的子序列
    codeforces 948A
    Splay 伸展树 bzoj3224 bzoj3223
    2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest C(gym/101142 C)
    2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest F(gym/101142 F)
    2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest G(gym/101142 G)
    Educational Codeforces Round 32 E 巨型背包
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12881685.html
Copyright © 2011-2022 走看看