HDU4513
马拉车处理数组,求数组的最长回文串,且要求数组前半部分呈递增状态。将原来处理马拉车的位置$和#写成类似与500与300等超过数字上限的大小。
这题最要注意的是处理递增序列的情况,while匹配扩增序列的时候,若匹配到之前的数为300继续,但是不更新与下一位比较的数。
注意数组的大小,且用scanf输入。
完整代码
#include <bits/stdc++.h> using namespace std; const int maxn=1000005; int mp[maxn*2],ma[maxn*2],s[maxn]; int n; int manacher() { int l=0; ma[l++]=500,ma[l++]=300; for(int i=0;i<n;i++) { ma[l++]=s[i]; ma[l++]=300; } ma[l]=0; int mx=0,id=0;//最长的回文串的右边界mx,和其中间点id for(int i=0;i<l;i++) { mp[i]=mx>i ? min(mp[2*id-i],mx-i) : 1; int k=ma[i]; //扩增序列时,300可以继续扩增,或是此位比下一位大,之后此位要更新成下一位 while(ma[i+mp[i]]==ma[i-mp[i]] && (ma[i-mp[i]]==300 || k>=ma[i-mp[i]])) { if(ma[i-mp[i]]!=300)//不为300才是原数组中的数 k=ma[i-mp[i]]; mp[i]++; } if(i+mp[i]>mx) { mx=i+mp[i]; id=i; } } return l; } int main() { int t; scanf("%d",&t); while(t--) { int ans=0; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&s[i]); int l=manacher(); for(int i=0;i<l;i++) ans=max(ans,mp[i]-1); printf("%d\n",ans); } return 0; }