P4287 [SHOI2011]双倍回文 解题报告
Desciption
给定一个字符串 $s$, 求 $s$ 的最长双倍回文子串。
双倍回文串定义为长度为4的倍数,并且满足 $WW^RWW^R$形式的字符串。
$W^R$ 为字符串 $W$ 的倒置。长度为偶数的普通回文串的形式为 $WW^R$。
Solution
~~貌似是 PAM 的基础题,不过我暂时不会。~~
看到回文串考虑 manachar。我们发现在 manachar 的实现过程中实际上证明了一个性质,就是一个串的本质不同的回文子串的个数是 $O(n)$ 的。而产生一个新的本质不同回文子串只有可能在更新 mx 的时候出现,这个时候直接暴力对每个新产生的回文子串判断一下即可。于是做完啦。
Code
#include<bits/stdc++.h> using namespace std; inline int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') f = -f; c = getchar();} while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();} return x * f; } const int N = 5e5 + 10; int n, p[N<<1]; char s[N], str[N<<1]; inline void manachar() { int len = 1, ans = 0; str[0] = '$'; str[1] = '#'; for (int i = 1; i <= n; ++ i) str[++len] = s[i], str[++len] = '#'; for (int i = 1, mx = 0, id = 0; i <= len; ++ i) { if (i < mx) p[i] = min(p[2*id-i], mx - i); else p[i] = 1; while (str[i+p[i]] == str[i-p[i]]) ++p[i]; if (i + p[i] > mx) { if (i & 1) for (int j = max(mx, i + 4); j < i + p[i]; ++ j) if (!(j-i & 3) && p[i-(j-i)/2] > (j-i)/2) ans = max(ans, j - i); mx = i + p[i], id = i; } } printf("%d\n", ans); } int main () { n = read(); scanf("%s", s + 1); manachar(); return 0; }

浙公网安备 33010602011771号