P4555 [国家集训队] 最长双回文串 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
原理比较简单,就是在传统马拉车算法的基础上,在区间边界统计数据,用的是分隔符处两边的统计,因为要求分割为两个回文子串。需要注意两个点。
1. 在manacher算法生成时,我们找到的是饱和的区间,所以会有统计不到的点,得另行顺序和逆序分别再生成一下。
2. 为了不因为一些诸如aba,aaccaa这样的本来就只有一个回文子串的数据影响, 我们最后统计ll+rr时跳过第一个和最后一个分隔符,防止统计了空字符+回文子串的组合。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int sz = 1, p[N << 1], ans, ll[N << 1], rr[N << 1];
char s[N << 1];
inline void rd() {
char c = getchar();
s[0] = '#', s[1] = '|';
while(c < 'a' || c > 'z') c = getchar();
while(c >= 'a' && c <= 'z') s[++sz] = c, s[++sz] = '|', c = getchar();
}
int main() {
rd();
for(int i = 1, mid = 0, r = 0; i <= sz; i ++ ) {
if(i <= r) p[i] = min(p[2 * mid - i], r - i + 1);
while(s[i - p[i]] == s[i + p[i]]) ++ p[i];
if(r < p[i] + i) r = p[i] + i - 1, mid = i;
ll[i + p[i] - 1] = max(ll[i + p[i] - 1], p[i] - 1);
rr[i - p[i] + 1] = max(rr[i - p[i] + 1], p[i] - 1);
}
for(int i = sz; i >= 1; i -= 2) ll[i] = max(ll[i], ll[i + 2] - 2);
for(int i = 1; i <= sz; i += 2) rr[i] = max(rr[i], rr[i - 2] - 2);
for(int i = 3; i <= sz - 2; i += 2) ans = max(ans, ll[i] + rr[i]);
cout << ans;
return 0;
}