首页 > 其他 > 详细

BZOJ 2565: 最长双回文串 [Manacher]

时间:2017-02-14 00:50:11      阅读:234      评论:0      收藏:0      [点我收藏+]

2565: 最长双回文串

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1842  Solved: 935
[Submit][Status][Discuss]

Description

顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。

Input

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

Output

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

Manacher后处理每个#左右最长被以L R为中心的回文串覆盖
答案用R-L来更新
 
我迷之TLE了40min
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=3e5+5;
typedef long long ll;
int n;
char s[N],str[N];
int r[N];
void Manacher(char s[],int n){
    int p=0,a;
    for(int i=1;i<=n;i++){
        r[i]=i<p?min(p-i+1,r[2*a-i]):1;
        while(s[i-r[i]]==s[i+r[i]]) r[i]++;
        if(i+r[i]-1>p) p=i+r[i]-1,a=i;
    }
}
void iniStr(char str[],char s[]){
    for(int i=1;i<=n;i++)
        s[(i<<1)-1]=#,s[i<<1]=str[i];
    s[n<<1|1]=#;
    s[0]=@;s[(n<<1)+2]=$;
}
int l[N];
int main(){
    freopen("in","r",stdin);
    scanf("%s",str+1);
    n=strlen(str+1);
    iniStr(str,s);
    Manacher(s,n<<1|1);
    n=n<<1|1;
    int now=1,ans=0;
    for(int i=1;i<=n;i++){
        while(now+r[now]-1<i) now++;
        l[i]=now;
    }
    now=n;
    for(int i=n;i>=1;i--){
        while(now-r[now]+1>i) now--;
        if(i&1) ans=max(ans,now-l[i]);
    }
    printf("%d",ans);
}

 

 

 

BZOJ 2565: 最长双回文串 [Manacher]

原文:http://www.cnblogs.com/candy99/p/6395817.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!