题解
用途:
求一个字符串中有多少个回文子串
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 3e7 + 10;
int p[N];//以i为回对称中心的最长回文串
int Manachar(string s) { // string类TLE警告
int len = s.length();
string t = "~|"; //构造新的字符串 ~结束符 |插入符
for (int i = 0; i < len; ++i) {
t = t + s[i] + '|'; // t+=s[i]+'|' 这样写是有问题的
// 构造类似 ~|A|B|C|C|B|A| 这样的字符串
}
len = t.length();
int res = 0;
int r = 0; // r 已经确定的右侧最靠右的回文串的右边界
int mid = 0; // mid 已经确定的右侧最靠右的回文串的对称中心
for (int i = 1; i < len; ++i) {
// i 枚举每个对称中心
if (i < r) p[i] = min(p[(mid << 1) - i], r - i);
else p[i] = 1;
while (t[i - p[i]] == t[i + p[i]])++p[i]; //暴力拓展左右两侧
if (p[i] + i > r) {
r = p[i] + i;
mid = i;
res = max(res, p[i]); //最长回文字串长度
}
}
return res - 1;
}
char s[N], t[N];
int Manachar(char *s) {
// 构造类似 ~|A|B|C|C|B|A| 这样的字符串
int len = strlen(s);
int cnt = 0;
t[cnt++] = '~';
t[cnt++] = '|';
for (int i = 0; i < len; ++i) {
t[cnt++] = s[i];
t[cnt++] = '|';
}
t[cnt] = 0;//字符串尾部设为0 防止越界
len = cnt;
int res = 0;
int r = 0; // r 已经确定的右侧最靠右的回文串的右边界
int mid = 0; // mid 已经确定的右侧最靠右的回文串的对称中心
for (int i = 1; i < len; ++i) {
// i 枚举每个对称中心
if (i < r) p[i] = min(p[(mid << 1) - i], r - i);
else p[i] = 1;
while (t[i + p[i]] == t[i - p[i]]) ++p[i]; //暴力拓展左右两侧
if (p[i] + i > r) {
r = p[i] + i;
mid = i;
res = max(res, p[i]); //最长回文字串长度
}
}
return res - 1;
}
int main() {
ios::sync_with_stdio(0);
scanf("%s", s);
cout << Manachar(s) << endl;
return 0;
}