Manacher算法:

http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/

hdu3068

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <map>
#include <stack>
#include <queue>
#include <set>
#include <cmath>
using namespace std;
#define _min(x, y) ((x)<(y)?(x):(y))
#define _max(x, y) ((x)>(y)?(x):(y))
char s_[320005];
char s[340010];
int p[340010];
int main()
{
    int ans,i,j,k,m,n,id,mx,cnt=0,len;
    while (scanf("%s",s_)!=EOF)
    {
        s[0]='^';
        s[1]='*';
        int n=strlen(s_);
        for (i=0;i<n;i++)
        {
            s[i*2+2]=s_[i];
            s[i*2+3]='*';
        }
        len=n*2+2;
        s[len]='\0';
        p[0]=id=mx=ans=0;
        for(i=len; s[i]!='\0'; i++)
            s[i] = '\0';
        for (i=1;i<len;i++)
        {
            if( mx > i )
                p[i] = _min( p[2*id-i], p[id]+id-i );
            else
                p[i] = 1;
            for(; s[i+p[i]] == s[i-p[i]]; p[i]++)
                ;
            if( p[i] + i > mx )
            {
                mx = p[i] + i;
                id = i;
            }
            ans=_max(ans,p[i]);
        }
        printf("%d\n",ans-1);
    }
    return 0;
}

多校multi-7-1003

先用求回文串的Manacher算法,求出以第i个点和第i+1个点为中心的回文串长度,记录到数组c中 比如 10 9 8 8 9 10 10 9 8 我们通过运行Manacher求出第i个点和第i+1个点为中心的回文串长度 0 0 6 0 0 6 0 0 0

两个8为中心,10 9 8 8 9 10是个回文串,长度是6。 两个10为中心,8 9 10 10 9 8是个回文串,长度是6。

要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,比如上边的两个字符串,共享 8 9 10这一部分。 也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样。 因为我们已经记录下来以第i个点和第i+1个点为中心的回文串长度, 那么问题可以转化成,相距x的两个数a[i],a[i+x],满足a[i]/2>=x 并且 a[i+x]/2>=x,要求x尽量大

这可以用一个set维护,一开始集合为空,依次取出a数组中最大的元素,将其下标放入set中,每取出一个元素,再该集合中二分查找比i+a[i]/2小,但最大的元素,更新答案。 然后查找集合中比i-a[i]/2大,但最小的元素,更新答案。

答案就是3*ans

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值