暑假训练round2 D: 好序列(Manacher)

来源:互联网 发布:考勤机更改下载数据 编辑:程序博客网 时间:2024/05/21 22:51

Problem 1061: 好序列


Time Limits:  1000 MS   Memory Limits:  65536 KB

64-bit interger IO format:  %lld   Java class name:  Main


Description

杨神觉得好的序列需要符合这两个条件
1.这段序列可以平均分成三段,第一段和第三段相同
2.第二段与第一段相反
给你一个由n个非负整数组成的序列,问连续子序列是好序列时,该连续子序列的长度是多少。

Input

第一行为t 代表t组测试数据
第二行为n ( 1 <= n <= 100000)代表序列由n个非负整数组成
第三行为n个数 (ai < 100000)

 

Output


开始为"Case #i: " 后面跟着一个整数,代表最长的连续子序列为好序列的长度

Sample Input

1102 3 4 4 3 2 2 3 4 4

Output for Sample Input

Case #1: 9

比赛的时候只知道用manacher,之后就感觉下标处理起来麻烦就没做了……,正确解法是枚举i的对称点i+p[i]-1,再从对称点再往回扫一遍,看看存不存在也能往回覆盖至i点,有的话就记录[当前点-i]为1.5段的长度即可。

代码:

#include<iostream>#include<algorithm>#include<cstdlib>#include<sstream>#include<cstring>#include<cstdio>#include<string>#include<deque>#include<stack>#include<cmath>#include<queue>#include<set>#include<map>using namespace std;#define INF 0x3f3f3f3f#define MM(x,y) memset(x,y,sizeof(x))#define LC(x) (x<<1)#define RC(x) ((x<<1)+1)#define MID(x,y) ((x+y)>>1)typedef pair<int,int> pii;typedef long long LL;const double PI=acos(-1.0);const int N=100010;int arr[N],p[N*2];int s[N*2];int n;void manacher(){MM(p,0);MM(s,0);int i, len=0;s[len++]=-2;s[len++]=-1;for (i=0; i<n; i++){s[len++]=arr[i];s[len++]=-1;}int mx=0, idd=0;for (i=0; i<len; i++){if(mx>i)p[i]=min(p[2*idd-i],mx-i);elsep[i]=1;while (s[i+p[i]]==s[i-p[i]])p[i]++;if(i+p[i]>mx){mx=p[i]+i;idd=i;}}}int main(void){int tcase, i, j, cnt=0;scanf("%d",&tcase);while (tcase--){MM(arr,0);scanf("%d",&n);for (i=0; i<n; i++)scanf("%d",&arr[i]);manacher();int ans=0;for (i=1; i<2*n+2; i+=2){for (j=i+p[i]-1; j-i>ans; j-=2)//往回遍历{if(j-(p[j]-1)<=i){if(j-i>ans){ans=j-i;break;}}}}printf("Case #%d: %d\n",++cnt,3*(ans>>1));}return 0;}

0 0
原创粉丝点击