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

bzoj2342 [Shoi2011]双倍回文 (manacher)

时间:2018-03-28 11:05:04      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:status   bzoj   pac   body   gpo   clu   upper   cpp   连续   

2342: [Shoi2011]双倍回文

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 3787 Solved: 1472
[Submit][Status][Discuss]

Description

技术分享图片

Input

输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

Output

输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。


看了好长时间,太差了;
\(R[k]\)为以\(k\)为中心的最长回文串,\(x\)\(ww^Rww^R\)对称轴,\(y\)为右半部分\(ww^R\)对称轴;
\(ch[x]\)\(ch[y]\)一定为特殊字符,所以一定满足\(R[x]>=2(y-x)\)\(R[y]>=y-x\)
\(x+R[x]/2>=y\)\(x>=y-R[y]\)
所以把\(y\)\(y-R[y]\)排序,枚举\(x\),把符合条件的\(y\)扔到\(set\)\(upper\)_\(bound\)一下就行了;
AC GET☆DAZE

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define N 1000039
#define mod 20070831
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
int n,m,R[N],stp[N],ans;
char ch[N],rea[N];
set<int> pos;
set<int>::iterator th;
int force(int &id,int &mx,int r)
{
    while(r<m)
    {
        if(rea[(id<<1)-r]!=rea[r]) break;
        R[id]++,mx=r++;
    }
}
void manacher()
{
    int id=1,mx=1;
    for(int a=1,b;mx<m && a<m;a++)
    {
        if(a>=mx) force(id=a,mx,a+1);
        else
        {
            b=(id<<1)-a;
            if(R[b]<mx-a) R[a]=R[b];
            else
            {
                R[a]=mx-a;
                force(id=a,mx,mx+1);
            }
        }
    }
}
bool cmp(int i,int j)
{
    return i-R[i]<j-R[j];
}
int main()
{
    scanf("%d",&n);
    scanf(" %s",&ch);
    rea[0]='3',rea[m=2*n+2]='9';
    for(int a=1;a<m;a++)
    {
        if(a&1) rea[a]='#';
        else rea[a]=ch[(a>>1)-1];
        stp[a]=a;
    }
    manacher();
    sort(stp+1,stp+m,cmp);
    for(int a=1,b=1;a<m;a+=2)
    {
        while(b<m && stp[b]-R[stp[b]]<=a)
        {
            if(stp[b]&1) pos.insert(stp[b]);
            b++;
        }
        th=pos.upper_bound(a+R[a]/2);
        if(th!=pos.begin())
        {
            th--;
            ans=max(ans,2*(*th-a));
        }
    }
    printf("%d",ans);
    return 0;
}

bzoj2342 [Shoi2011]双倍回文 (manacher)

标签:status   bzoj   pac   body   gpo   clu   upper   cpp   连续   

原文地址:https://www.cnblogs.com/Sinogi/p/8662255.html

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