給定一個字符串,求這個字符串有多少個迴文串或者最長迴文串是哪個。我用是以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;
}