hdu5371(O(n)求回文子串的相关问题)

来源:互联网 发布:视频配音软件 编辑:程序博客网 时间:2024/06/13 14:17

题意:

给出一个最多有10^5次方个数字的序列,找出其中最长的N-sequence的长度。N-sequence的定义如下:

找出原串中的一个连续的子串,分成相等的三部分,第一部分和第二部分要形成一个回文串,第二部分和第三部分要形成一个回文串,第一部分要和第三部分相等。


思路:

我们先用manacher算法在O(n)的时间内求出所有的以第i位为回文串中心的回文串的长度,然后找出每一个回文串最长能伸展到哪一位,记录下来。然后我们枚举以i位中心的回文串(枚举i),每次我们在存好的set中找满足情况离i最远的下标,然后把i插入set,当我们枚举的i到达了某个个回文串能伸展到的最长的位置,我们要把那个回文串中点的下标从set中删除,如此往复,维护ans的最大值。


代码:

#include<iostream>  #include<cstring>  #include<cstdlib>  #include<cstdio>  #include<climits> #include<vector>#include<algorithm> #include<set>using namespace std;    const int maxn=100050;  vector<int> a;int rad[maxn*2];vector<int> vec[maxn*2];set<int> ss;void manacher() {    memset(rad,0,sizeof(rad));    int n = a.size();    int i,j,k;    i=0;    j=1;    while(i<n)    {        while(i-j>=0 && i+j<n && a[i-j]==a[i+j])            j++;        rad[i]=j-1;        k=1;        while(k<=rad[i] && rad[i]-k!=rad[i-k])        {            rad[i+k]=min(rad[i-k],rad[i]-k);            k++;        }        i += k;        j = max(j-k,0);    }}int main()  {      int t;    scanf("%d",&t);    int cas=1;    while(t--)    {        int n;        scanf("%d",&n);        a.clear();        for (int i = 0; i < n; i++)         {            int x;            scanf("%d", &x);            a.push_back(-1);            a.push_back(x);        }        a.push_back(-1);        manacher();                int len=a.size();for(int i=0;i<200040;i++)vec[i].clear();        for(int i=0;i<len;i++)if(a[i]==-1)            vec[i+rad[i]].push_back(i);     //   for (int i = 0; i < a.size(); i++) {     //       printf("%2d ", i);     //   }puts("");     //   for (int i = 0; i < a.size(); i++) {     //       printf("%2d ", a[i]);     //   }puts("");     //   for (int i = 0; i < a.size(); i++) {     //    printf("%2d ", rad[i]);     //   }puts("");int ans=0;ss.clear();for(int i=0;i<len;i++){if(a[i]==-1){int findnum=i-rad[i];//printf("i=%d find=%d\n",i,findnum);set<int>::iterator iter;//for(iter=ss.begin();iter!=ss.end();iter++)//printf("%d ",*iter);//printf("\n");iter=ss.lower_bound(findnum);if(iter!=ss.end()){int nnnn=*iter;//printf("nnn=%d\n",nnnn);int rrr=min(rad[nnnn],rad[i]);rrr=min(rrr,i-nnnn);ans=max(ans,rrr/2*3);//printf("ans=%d\n------------\n",ans);}ss.insert(i);}if(vec[i].size()!=0){for(int j=0;j<vec[i].size();j++)ss.erase(vec[i][j]);}}        printf("Case #%d: ",cas++);        printf("%d\n",ans);    }    return 0;  }  


0 0