标签:
问题描述:
找一个字符串里的最长回文子串
暴力法:定中心,从0长度向两端扩展的方法O(n^2), n >= 10^5还是超时,故只能《O(n^2)
Manacher‘s 算法:定中心,从p[r],(已能确定以该点为中心两端是回文的长度开始), 向两端扩展,时间复杂度, O(n)
算法如下:
示意图:
定义:
cen:当前中心点以r为中心,向两端扩展则时间复杂度为O(n^2)
原理实现:
#include<string>
#include<iostream>
#include<vector>
using namespace std;
void solve(string s) {
int l, r;
int len = s.length();
int cen = 0;
vector<int> p;
p.push_back(0);
for (r = 0; r < len; r++) {
printf("cen = %d, pcen = %d, r = %d\n", cen, p[cen], r);
p.push_back(0);
int cenR = cen + p[cen];
if (r <= cenR) {
l = 2 * cen - r;
p[r] = p[l] < cenR - r ? p[l] : cenR - r;
} else {
p[r] = 0;
}
// 这里是关键,如果从r为中心长度为0开始向两边扩展,则复杂度为O(n^2), 这里从p[r]开始扩展
while((r-p[r]-1>=0) && (r+p[r]+1<len) && (s.at(r - p[r] -1) == s.at(r + p[r] + 1))) p[r]++;
if (r + p[r] >= cenR) {
cen = r;
}
}
cout << s << endl;
int i;
for (i = 0; i < len; i++) {
printf("%d ", p[i]);
} printf("\n");
}
int main() {
solve("11111111111");
return 0;
}
标签:
原文地址:http://blog.csdn.net/zhong123123123/article/details/51329978