BZOJ2565: 最长双回文串(回文树) BZOJ2565: 最长双回文串(回文树)

BZOJ2565: 最长双回文串(回文树)

知识点:1.前后扫描两次字符串,分别建回文树。

#include <bits/stdc++.h>
using namespace std;
const long long MAXN = 100002; 
struct PAM
{
    char c[MAXN];
    long long ch[MAXN][26];
    long long fail[MAXN],len[MAXN],cnt[MAXN];
    long long tot,last;
    long long newnode(long long lg)
    {
        len[++tot] = lg;
        return tot;
    }
    void init()
    {
        tot = -1;
        newnode(0);
        newnode(-1);
        fail[0] = 1;
        c[0] = '~';
        last = 0;
    }
    long long getfail(long long x,long long mid)
    {
        while(c[x - len[mid] - 1] != c[x])mid = fail[mid];
        return mid;
    }
    long long insert(long long t)
    {
        long long x = getfail(t,last);
        long long u = c[t] - 'a';
        if(!ch[x][u])
        {
            long long y = newnode(len[x] + 2);
            fail[y] = ch[getfail(t,fail[x])][u];
            ch[x][u] = y;
         } 
         cnt[last = ch[x][u]]++;
         return len[ch[x][u]];
    }
}a1,a2;
long long maxn[MAXN + 2];
int main()
{
    scanf("%s",a1.c + 1);
    a1.init();
    a2.init();
    long long l = strlen(a1.c + 1);
    for(long long i = 1;i <= l;i++)a2.c[l - i + 1] = a1.c[i];
    for(long long i = 1;i <= l;i++)
    {
        maxn[i] = a1.insert(i); 
    }   
    long long ans = -1;
    for(long long i = 1;i <= l - 1;i++)//Wrong 1 : 一开始写成了for(int i = 1;i <= l;i++),应该是l - 1而不是l,因为最头分界点只能是第二个点。 
    {
        long long t = a2.insert(i);
        ans = max(ans,t + maxn[l - i]);
    }
    printf("%lld",ans);
    return 0;
}  

猜你喜欢

转载自www.cnblogs.com/xyj1/p/10663181.html