P4555 [国家集训队]最长双回文串(回文树)

题目描述

顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同)。

输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可将 T 分为两部分 X , Y ,( |X|,|Y|≥1 )且 X 和 Y都是回文串。

输入输出格式

输入格式:

一行由小写英文字母组成的字符串 S 。

输出格式:

一行一个整数,表示最长双回文子串的长度。

输入输出样例

输入样例#1: 复制

baacaabbacabb

输出样例#1: 复制

12

说明

【样例说明】

从第二个字符开始的字符串aacaabbacabb可分为aacaabbacabb两部分,且两者都是回文串。

对于100%的数据, 2≤|S|≤10^5


题解

直接顺序回文树统计一遍每一位结尾的回文串的长度
再倒序统计一遍
最后暴力遍历一遍统计的结果就好了。


代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
struct node{
    int len,ch[26],fail;
}t[100001];
int f[100001],g[100001],tot;
char s[100001];
int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}

void solve1()
{
    int len=strlen(s+1),k=0;s[0]='$';
    t[0].fail=1;t[1].len=-1;tot=1;
    for(int i=1;i<=len;i++)
    {
        while(s[i-t[k].len-1]!=s[i])k=t[k].fail;
        if(!t[k].ch[s[i]-'a']){
            t[++tot].len=t[k].len+2;
            int j=t[k].fail;
            while(s[i-t[j].len-1]!=s[i])j=t[j].fail;
            t[tot].fail=t[j].ch[s[i]-'a'];
            t[k].ch[s[i]-'a']=tot;
        }
        k=t[k].ch[s[i]-'a'];
        f[i]=t[k].len;
    }
}

void solve2()
{
    int len=strlen(s+1),k=0;s[0]='$';
    t[0].fail=1;t[1].len=-1;tot=1;
    for(int i=1;i<=len;i++)
    {
        while(s[i-t[k].len-1]!=s[i])k=t[k].fail;
        if(!t[k].ch[s[i]-'a']){
        t[++tot].len=t[k].len+2;
        int j=t[k].fail;
        while(s[i-t[j].len-1]!=s[i])j=t[j].fail;
        t[tot].fail=t[j].ch[s[i]-'a'];
        t[k].ch[s[i]-'a']=tot;
        }
        k=t[k].ch[s[i]-'a'];
        g[len-i+1]=t[k].len;
    }
}

int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    solve1();
    reverse(s+1,s+len+1);
    memset(t,0,sizeof(t));
    solve2();
    int ans=0;
    for(int i=1;i<len;i++)ans=max(ans,f[i]+g[i+1]);
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/hhh1109/p/9246011.html

时间: 2024-08-27 18:58:16

P4555 [国家集训队]最长双回文串(回文树)的相关文章

P4555 [国家集训队]最长双回文串

题意:求这样一个回文串S,S = A + B 且 A, B都是回文串.问最长S 题解:建立两颗回文树,一个从前向后插,一个从后向前插,并记录每个位置得到的最长后缀后文. ps:马拉车的做法待更 const int N = 100005; struct data { int len, fail; int ch[26]; }; struct PldTree { int tot, last; int cnt[N]; char s[N]; data node[N]; void Inite() { tot

【[国家集训队]最长双回文串】

可能还是非常板子的\(Manacher\) 还是先跑一遍\(Manacher\)处理出来所有的回文半径\(r[i]\) 由于我们要找的答案是两个回文串拼了起来,所以我们考虑枚举中间这个拼接处 所以我们要找到每一个\(i\),其左边能够到达\(i\)的和右边能到达\(i\)的最大的回文半径 显然并不能直接使用\(i+r[i]\)和\(i-r[i]\)因为回文半径可以是比\(r[i]\)小的,用小的回文半径可以拼出更大的双回文串 显然如果\(i+r[i]-1\)也是可以使用\(i\)为中心的回文半径

HYSBZ 2565 最长双回文串 (回文树)

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1377  Solved: 714 [Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y

BZOJ 3676: [Apio2014]回文串 回文串自动机

裸的回文串自动机 3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 504  Solved: 152 [Submit][Status][Discuss] Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的"出 现值"为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s

【bzoj3676】[Apio2014]回文串 回文自动机

题目描述 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最大出现值. 输入 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. 输出 输出一个整数,为逝查回文子串的最大出现值. 样例输入 [样例输入l] abacaba [样例输入2] www 样例输出 [样例输出l] 7 [样例输出2] 4 题解 回文自动机裸题 关于PAM个人暂时理解不是很深入,挖坑待填. 本题只需要统计fail树的子树大小,再

bzoj 3676: [Apio2014]回文串 回文自动机

3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 844  Solved: 331[Submit][Status][Discuss] Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. Output 输出一个整数,

HYSBZ 3676 回文串 (回文树)

3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1680  Solved: 707 [Submit][Status][Discuss] Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的"出 现值"为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. Output

hysbz3676 回文串 回文自动机

回文自动机模板题 头铁了一下午hdu6599,最后发现自己的板有问题 先放这里一个正确性得到基本确认的板,过两天肝hdu6599 #pragma GCC optimize(2) #include<bits/stdc++.h> #include<iostream> #include<cstring> #include<cassert> #define MAXN 300010 #define LL long long #define BASE 2LL #defi

bzoj3676: [Apio2014]回文串 回文树

回文树的裸题. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=500100; const int INF=1e9+10; struct PalinTree { int ch[maxn][26],f[maxn]; int