采用在数字之间插入不可能数据(-1)
如:1 2 1
变为:-1 1 -1 2 -1 1 -1
利用性质:p[i] >= min(rem.right - i, odd[rem.left + (rem.right - i)])
我的理解:假设在前面某点mid,确定一个回文区间[rem[mid].left, rem[mid].right];而当以i(rem[mid].right > i > mid)为中点,
求它往两边发散的回文半径,可以利用i关于mid对称的点rem[mid].left + rem[mid].right - i已经算出的回文半径,再想两边发散,
不过也得受rem[mid].right - i限制,也就是
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 100005
int a[MAXN * 2];
struct Rem{
int left;
int right;
}rem;
int odd[2 * MAXN];
int min(int a, int b)
{
return (a < b) ? a : b;
}
int fun(int i, int m, int N)
{
int l = i - m - 1, r = i + m + 1;
int ret = 0;
for(;(l > 0)&&(r <= N);--l, ++r)
{
if((a[r] == -1) || ((a[l] == a[r]) && ((r - l == 2)||(a[r] <= a[r - 2]) )))
++ret;
else break;
}
return ret;
}
int main()
{
int T, N;
for(scanf("%d", &T); T--; )
{
scanf("%d", &N);
int i = 0;
a[++i] = -1;
while(N--)
{
scanf("%d", &a[++i]);
a[++i] = -1;
}
N = i;
rem.left = rem.right = 0;
int ans = 1;
memset(odd, 0, sizeof(odd));
for(int i = 1; i <= N; ++i)
{
int m = 0;
if(rem.right > i)
m = min(rem.right - i, odd[rem.left + (rem.right - i)]);//利用对称左右对称性质优化
odd[i] = m + fun(i, m, N);
if(i + odd[i] > rem.right)//当有最大右边覆盖,记录下来
{
rem.left = i - odd[i];
rem.right = i + odd[i];
}
if(odd[i] > ans)
ans = odd[i];
}
printf("%d\n", ans);
}
return 0;
}