题目 :
就是一个求最大回文子串的模板题 :
方法一 : 中心扩展 时间复杂度(O(n^2))
之前在leetcode上就是用的中心扩展做的, 勉强过了
中心扩展思路很简单, 就是遍历一遍字符串, 然后对于每一个字符都向左右扩展求最大回文串
这道题的中心扩展代码 :
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2000000 + 5;
#define debug(x)
(void)(cerr << "L" << __LINE__
<< " : " << #x << " = "
<< (x) << endl )
int judge(string s) {
string ss = "";
for (int i = 0; i < s.size(); ++i) {
ss += '#';
ss += s[i];
}
ss += '#';
int ptr = 0;
int ans = -1;
while (ptr < ss.size() - 1) {
int k = 1;
int sum = ( ss[ptr] == '#' ? 0 : 1 );
while (ptr + k < ss.size() && ptr - k >= 0 && ss[ptr + k] == ss[ptr - k])
{
sum += ( ss[ptr + k] == '#' ? 0 : 2 );
k++;
}
ptr++;
ans = max(ans, sum);
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
string s;
int i = 1;
while (cin >> s && s != "END") {
cout << "Case " << i++ << ": " << judge(s) << endl;
}
return 0;
}
由于时间复杂度太高, 这题TLE, 被迫学习manachar
方法二 : manachar 时间复杂度(O(n))
因为这个算法有点牛逼, 我直接另开一篇博客记录一下
本质就是利用了回文串的对称性, 避免了中心扩展的许多重复操作
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
const int maxn = 2000000 + 5;
int lens[maxn];
void reIO() {
#ifndef ROCCOSHI
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
}
#define debug(x)
(void)(cerr << "L" << __LINE__
<< " : " << #x << " = "
<< (x) << endl )
string expand(string s) {
string ss = "$";
for (int i = 0; i < s.size(); ++i) {
ss += '#';
ss += s[i];
}
ss += "#^";
return ss;
}
int manachar(string s) {
int mx = 0;
int pos = 0;
int ans = -1;
for (int ptr = 1; ptr < s.size() - 1; ++ptr) {
if (ptr < mx)
lens[ptr] = min (lens[2 * pos - ptr], mx - ptr);
else
lens[ptr] = 1;
while (s[ptr - lens[ptr]] == s[ptr + lens[ptr]])
lens[ptr]++;
if (mx < ptr + lens[ptr]) {
mx = ptr + lens[ptr];
pos = ptr;
}
ans = max (ans, lens[ptr] - 1);
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
reIO();
string s;
int i = 1;
while (cin >> s && s != "END") {
s = expand(s);
cout << "Case " << i++ << ": " << manachar(s) << endl;
}
return 0;
}