BZOJ [2565: 最长双回文串]

题意:

给出一个字符串 S S S,求 S S S的最长双回文子串 T T T,即可将 T T T分为两部分 X X X Y Y Y ( ∣ X ∣ , ∣ Y ∣ ≥ 1 ) (|X|,|Y|≥1) X,Y1 X X X Y Y Y都是回文串。

题解:

我们知道 l e n [ i ] len[i] len[i]表示以 i i i这个字符结束的最长回文串的长度,然后我们只需要建立两个回文自动机(一个正向一个反向)就可以啦!
详细细节见代码!

A C AC AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int MAXN = 5e5+50;
struct Palind{
    int nxt[MAXN][26],fail[MAXN],len[MAXN],cnt[MAXN];
    char str[MAXN];
    int sz,lst,sn;
    void Init(){
        fail[0] = fail[1] = 1;
        len[0] = 0,len[1] = -1;
        sz = lst = 1;
        sn = 0;
        str[0] = '#';
    }
    int Insert(char ch){
        str[++sn] = ch;
        int root = lst;
        while(str[sn]!=str[sn-len[root]-1]) root = fail[root];
        if(!nxt[root][ch-'a']){
            len[++sz] = len[root] + 2;
            int tmp = fail[root];
            while(str[sn]!=str[sn-len[tmp]-1]) tmp = fail[tmp];
            fail[sz] = nxt[tmp][ch-'a'];
            nxt[root][ch-'a'] = sz;
        }
        lst = nxt[root][ch-'a'];
        return len[lst];
    }
}PAM1,PAM2;
char s[MAXN];
int lx[MAXN],ly[MAXN];
int main(){
    scanf("%s",s+1);
    int len = strlen(s+1);
    PAM1.Init(),PAM2.Init();
    for(int i=1;i<=len;i++) lx[i] = PAM1.Insert(s[i]);
    for(int i=len;i>=1;i--) ly[i] = PAM2.Insert(s[i]);
    int res = 0;
    for(int i=1;i<=len-1;i++)
        res = max(res,lx[i]+ly[i+1]);
    //用原串来解释,lx[i]就是以i为结束的回文串的长度,可以看作向左进行拓展的最长长度
    //ly[i+1]就是以i+1为结束的回文串的长度,看作向右拓展的最长长度
    cout<<res<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值