\(O(n)\) 時間求出字符串的最長回文子串。
數組
#include <bits/stdc++.h>
using namespace std;
const int N = 2e7;
char s[N << 1], ss[N];
int n, ans, p[N << 1];
void manacher(){
//預處理字符串
s[0] = '-', s[1] = '#';
for (int i = 0; i < n; i ++ ){
s[2 * i + 2] = ss[i];
s[2 * i + 3] = '#';
}
n = 2 * n + 1;
s[n + 1] = '+'; //計算回文子串的數量時,要記得清空,消除之前的字符對當前答案的影響
//p[i] 為第 i 個字符為中心的最大回文子串的半徑(字符串 s 的)
//p[i] - 1 為原字符串中第 i 個字符的回文串長度
int mid = 0, r = 0;
for (int i = 1; i < n; i ++ ){
p[i] = i < r ? min(p[(mid << 1) - i], r - i) : 1;
while (s[i - p[i]] == s[i + p[i]]) p[i]++;
if (i + p[i] > r){
r = i + p[i];
mid = i;
}
ans = max(ans, p[i] - 1); //求最長回文串長度
}
cout << ans << "\n";
}
int main(){
cin >> ss;
n = strlen(ss);
manacher();
return 0;
}
vector
string s;
cin >> s;
int n = s.length();
string t = "-#";
for (int i = 0; i < n; i ++ ){
t += s[i];
t += '#';
}
int m = t.length();
t += '+';
int mid = 0, r = 0;
vector<int> p(m);
for (int i = 1; i < m; i ++ ){
p[i] = i < r ? min(p[(mid << 1) - i], r - i) : 1;
while (t[i - p[i]] == t[i + p[i]]) p[i]++;
if (i + p[i] > r){
r = i + p[i];
mid = i;
}
}
洛谷模板: https://www.luogu.com.cn/problem/P3805
acwing模板: https://www.acwing.com/problem/content/3190/
洛谷題目:
https://www.luogu.com.cn/problem/P1659 前綴和 + manacher
https://www.luogu.com.cn/problem/P4555 manacher
https://www.luogu.com.cn/problem/P5446 manacher
https://www.luogu.com.cn/problem/P6216 kmp + manacher + 前綴和
浙公網安備 33010602011771號