版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
给定一个字符串 ,求这个字符串有多少个回文串或者最长回文串是哪个。我用 是以i为中心长度为奇数的回文串个数, 是以i为中心长度为偶数的回文串个数,则对字符串s而言, 。对于字符串 , 。用最朴素的枚举法可以在 内求出 ,程序如下:
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
string s; cin >> s;
int n = s.length();
vector<int> d1(n), d2(n);
for (int i = 0; i < n; i++) {
d1[i] = 1;
while (0 <= i - d1[i] && i + d1[i] < n && s[i - d1[i]] == s[i + d1[i]]) {
d1[i]++;
}
d2[i] = 0;
while (0 <= i - d2[i] - 1 && i + d2[i] < n &&
s[i - d2[i] - 1] == s[i + d2[i]]) {
d2[i]++;
}
}
for(int i = 0; i < n; i++) cout << d1[i] << " " << d2[i] << endl;
return 0;
}
- 是以i为中心的回文串个数
- 是字符串总的回文串个数
- 为字符串最长回文串长度
可见,如果求出 ,所有关于字符串的问题都将迎刃而解。但上面朴素的解法未免太过低效,需要更快的解法,于是便有了manacher算法。
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
string s; cin >> s;
int n = s.length();
vector<int> d1(n);
for (int i = 0, l = 0, r = -1; i < n; i++) {
int k = (i > r) ? 1 : min(d1[l + r - i], r - i);
while (0 <= i - k && i + k < n && s[i - k] == s[i + k]) {
k++;
}
d1[i] = k--;
if (i + k > r) {
l = i - k;
r = i + k;
}
}
vector<int> d2(n);
for (int i = 0, l = 0, r = -1; i < n; i++) {
int k = (i > r) ? 0 : min(d2[l + r - i + 1], r - i + 1);
while (0 <= i - k - 1 && i + k < n && s[i - k - 1] == s[i + k]) {
k++;
}
d2[i] = k--;
if (i + k > r) {
l = i - k - 1;
r = i + k;
}
}
for(int i = 0; i < n; i++) cout << d1[i] << " " << d2[i] << endl;
return 0;
}