HDU4513(manacher) 发表于 2019-08-15 | 阅读次数: 题目链接 做法:题目有三个要求,前两个要求是回文子串,第三个要求是回文前半部分递增。我们用manacher处理前两个要求,对于第三个要求,我们额外使用一个递增数组来记录当前位置前递增的数字数量。 代码:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182#include <bits/stdc++.h>using namespace std;const int maxn = 210000;int ma[maxn * 2];int mp[maxn * 2];int s[maxn];void manacher(int n){ int l = 0; ma[l++] = 99999; ma[l++] = 88888; for (int i = 0; i < n; i++) { ma[l++] = s[i]; ma[l++] = 88888; } ma[l] = 0; int mx = 0, id = 0; for (int i = 0; i < l; i++) { mp[i] = mx > i ? min(mp[2 * id - i], mx - i) : 1; while (ma[i + mp[i]] == ma[i - mp[i]]) mp[i]++; if (i + mp[i] > mx) { mx = i + mp[i]; id = i; } }}int dz[maxn];void fun_dz(int n) //记录该位置之前的递增数{ dz[0] = 0; for (int i = 1; i < n; i++) { if (s[i - 1] <= s[i]) { dz[i] = dz[i - 1] + 1; } else dz[i] = 0; }}int main(){ int len, t; cin >> t; while (t--) { scanf("%d", &len); for (int i = 0; i < len; ++i) scanf("%d", &s[i]); manacher(len); fun_dz(len); int maxans = 0; // for(int i=0 ;i<len*2+2;i++) // printf("%d ",mp[i]-1); // printf("\n"); for (int i = 2, j = 0; i < len * 2 + 2; i += 2, j++) { // printf("%d %d\n", mp[i] - 1, dz[j]); if ((mp[i] - 1) / 2 <= dz[j]) { maxans = max(maxans, mp[i] - 1); } } for (int i = 1, j = 0; i < len * 2 + 2; i += 2, j++) { // printf("%d %d\n", mp[i] - 1, dz[j]); if ((mp[i] - 1) / 2 <= dz[j]) { maxans = max(maxans, mp[i] - 1); } } printf("%d\n", maxans); } return 0;}