hdu5371 Hotaru's problem(manacher 算法+枚举)

来源:互联网 发布:数据库漏洞扫描 编辑:程序博客网 时间:2024/05/16 17:28

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371

题目大意:给一串数字,在子串中找到“1-2-1”的形式,其中1和2 是回文串,找出最长的那一串。

思路:利用manacher算法得出最长序列。观察子串形式,1和2是回文串,其实2和后面那个1也是回文串。

在之前我们已经通过manacher算法得到了每个数字所能延伸的长度,所以我们只要枚举第二段到第三段的距离即可。

当遇到第i个数字时,那么第二段和第三段的距离就是i+p[i],令j=i+p[i]-1,那么对于j这个位置就有p[j],我们只要j-(p[j]-1) <= i 就可以了。

这里的意思就是:j的回文半径大于i的回文半径,这样就能保证第二段和第三段也是回文串了。

注意有个优化:如果j-i<max,那么久不需要去看了。

#include<stdio.h>#include<string.h>#define min(a,b) a<b?a:bint str[220005],s[220005];int len,p[220005],a[22005];void solve(){    int i,mx,id;    mx=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(;str[p[i]+i]==str[i-p[i]];p[i]++)             ;        if(p[i]+i>mx){            mx=p[i]+i;            id=i;        }    }}void init(){    str[0]=-1;str[1]=-2;    for(int i=0;i<len;i++)    {        str[i*2+2]=a[i];        str[i*2+3]=-2;    }    len=len*2+2;    str[len]=-2;}int main(){    int i,j,k,T,t=0;scanf("%d",&T);    while(T--)    {        t++;     scanf("%d",&len);     memset(p,0,sizeof(p));      for(i=0;i<len;i++)      {scanf("%d",&a[i]);    //   s[i]=a[i]+'0';    }      init();      solve();          int ans=0;      int maxi=0;      int f=0;      for(i=1;i<len;i+=2)      {       for(j=i+p[i]-1;j-i>maxi;j-=2)    //只要看-2的位置即可。     {          if(j-p[j]+1<=i){          maxi=j-i;              break;      }         }            }      maxi=maxi/2*3;      printf("Case #%d: ",t);      printf("%d\n",maxi);    }    return 0;}/*141 2 2 1 1 2 3 3 2 1 1 2 3 4*//*100 15 1 2 3 4 5 5 4 3 2 1 1 2 3 4 5 15 3 4 5 5 4 3 2 1 1 2 3 4 5 5 4 10 2 3 4 4 3 2 2 3 4 4 11 1 1 2 3 3 2 1 1 2 3 3 */


0 0