hdu5371 Hotaru's problem (Manacher)

来源:互联网 发布:生意参谋免费版 知乎 编辑:程序博客网 时间:2024/04/29 20:47

/*像我这种菜鸡果然还是要写写博客,不然有的题目真是过去就过去了的状态。自己在硬盘里的代码也不太好管理,等以后写个软件来搞就好了 -  - */

题意:

给出一个串,找出满足以下条件的最长子串:

1. the first part is the same as the thrid part,

第一个部分和第三个部分一样。
2. the first part and the second part are symmetrical.

第一个部分和第二个部分对称。

思路:

这道题其实就是马拉车算法的简单应用

从题意出发  我们发现其实他想说的是 :

(设把s的一个子串分成三个子串   第i个子串为si)

|s1|==|s2|==|s3|

s1+s2是回文串

s2+s3是回文串

所以我们用马拉车(就爱说这个 -   -)可以知道其实就是求最长的一个子串满足:

设:s1和s2中间的分隔符为中心的回文串的长度p1

     s2和s3中间的分隔符为中心的回文串的长度p2

min(p1,p2)-1>=|s2|

一开始是对于每个分隔符暴力找  若找到则记录长度 

但是TLE了 -  -

所以  对j的循环做了一些优化 若小于所记录的就跳出

代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <cassert>using namespace std;const int MAXN = 1e6+10;int p[MAXN];//适用于正负整数template <class T>inline bool scan_d(T &ret) {   char c; int sgn;   if(c=getchar(),c==EOF) return 0; //EOF   while(c!='-'&&(c<'0'||c>'9')) c=getchar();   sgn=(c=='-')?-1:1;   ret=(c=='-')?0:(c-'0');   while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');   ret*=sgn;   return 1;}int Proc(int pszIn[],int pszOut[],int len){    int nLen=1;    pszOut[0]=0;    int i=0;    while(i<len)    {        pszOut[nLen++]=-1;        pszOut[nLen++]=pszIn[i];        i++;    }    pszOut[nLen++]=-1;    pszOut[nLen]=-2;    return nLen;}void Manacher(int *p,int *str,int len){    int mx=0,id=0;    for(int i=0;i<len;i++)    {        p[i]=mx>i?min(p[2*id-i],mx-i):1;        while(str[i+p[i]]==str[i-p[i]])p[i]++;        if(i+p[i]>mx)        {            mx=i+p[i];            id=i;        }    }}int check(int len){    long long cnt=0;    int ret=0;    for(int i=1;i<=len;i+=2)    {        if(p[i]>2)            for(int j=(i+min(((p[i]>>1)<<1),((len>>1)/3)*2));j>i&&ret<(j-i)+1;j-=2,cnt++)                if(min(p[i],p[j])>=(j-i)+1)                    ret=(j-i)+1;    }    return ret;}int in[MAXN],out[MAXN<<2];int main(){    int T,cas=1;    scan_d(T);    while(T--)    {        int n;        scan_d(n);        for(int i=0;i<n;i++)            scan_d(in[i]);        n=Proc(in,out,n);        Manacher(p,out,n);        printf("Case #%d: %d\n",cas++,(check(n)/2)*3);    }    return 0;}


0 0
原创粉丝点击