码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2565: 最长双回文串

时间:2018-01-07 23:36:15      阅读:336      评论:0      收藏:0      [点我收藏+]

标签:turn   时间复杂度   targe   cto   def   strlen   http   line   min   

传送门

今天来学回文自动机的模板吧!Achen开心地告诉自己,然后打开了一道水题。

噫,这不是马拉车的水题嘛、、

第一反应,马拉车,然后线段树维护第i个字母结尾的最长回文串长度

然后其实做法应该是线性的,傻了吧,,,

考虑马拉车的时候往后拓展,容易想到每个点第一次被拓展到的时候的那个店就是以它为结尾的最长回文串的回文中心。

然后正反跑马拉车,枚举一下分割点统计答案即可,整体的时间复杂度也是O(n)的。

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=2e5+7; 
typedef long long LL;
using namespace std;
int ans,len,n,l[N],r[N],rad[N];
char s[N],ss[N];

void manacher(int ll[]) {
    for(int i=1,k=0,j,now=0;i<n;) {
        while(s[i-k-1]==s[i+k+1]) k++;
        rad[i]=k;
        while(now<n&&i+rad[i]>=now) {
            ll[now]=i;
            now++;
        }
        for(j=1;j<=k&&rad[i-j]!=rad[i]-j;j++) 
            rad[i+j]=min(rad[i-j],rad[i]-j);
        k=max(k-j,0);
        i+=j;
    }
}

int is(char ch) {return ch>=a&&ch<=z;}

int main() {
    scanf("%s",ss);
    int len=strlen(ss);
    s[n++]=*; s[n++]=&;
    for(int i=0;i<len;i++) {
        s[n++]=ss[i];
        s[n++]=&; 
    }
    s[n++]=#;
    manacher(l);
    memset(rad,0,sizeof(rad));
    for(int i=0;i<=n/2;i++) swap(s[i],s[n-i-1]);
    manacher(r);
    for(int i=1;i<n-4;i++) if(is(s[i])) {
        int a=i-r[i]+1,b=n-(i+2)-1-l[n-(i+2)-1]+1;
        ans=max(ans,a+b);
    }
    printf("%d\n",ans); 
    return 0;
}
View Code

改天来补回文自动机的做法。

bzoj2565: 最长双回文串

标签:turn   时间复杂度   targe   cto   def   strlen   http   line   min   

原文地址:https://www.cnblogs.com/Achenchen/p/8232509.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!