\(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 + 前缀和

posted on 2022-04-05 21:20  Hamine  阅读(30)  评论(0编辑  收藏  举报