什么是回文串,所谓回文串,简单来说就是正着读和反着读都是一样的字符串,比如ababa,abba等等,一个字符串的最长回文子串即为这个字符串的子串中,是回文串的最长的那个。
一种比较常见的算法:枚举长度。时间复杂度的平方级别的
之前写的java代码:
public class 最长回文子串 {
static int min = 0, max = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] c = sc.nextLine().toCharArray();
int n = c.length;
boolean[][] ok = new boolean[n+1][n+1];
// 初始化
// 长度1
for(int i=0; i<n; i++)
ok[i][i] = true;
// 长度2
for(int i=0; i+1<n; i++) {
if(c[i]==c[i+1]) {
ok[i][i+1] = true;
min = i;
max = i+1;
}
}
// 长度3
for(int i=0; i+2<n; i++) {
if(c[i] == c[i+2]) {
ok[i][i+2] = true;
min = i;
max = i+2;
}
}
// 长度为4或以上的区间
for(int k=4; k<=n; k++) {
for(int i=0; i+k-1<n; i++) {
int j = i+k-1;
if(c[i]==c[j] && ok[i+1][j-1]) {
ok[i][j] = true;
min = i;
max = j;
}
}
}
for(int i=min; i<=max; i++) {
System.out.print(c[i]);
}
}
}
这里介绍一个能够在线性时间求解的算法
博主比较懒而且字比较丑见谅!!!其实博主不会画图…
c++代码
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1000010;
char s[1000010];
char str[1000010<<1];
int len[1000010<<1];
int Min = 0, Max = 0;
int init(char* s){
int n = strlen(s);
str[0] = '%';
for(int i=1; i<=2*n; i+=2){
str[i] = '#';
str[i+1] = s[i/2];
}
str[2*n+1] = '#';
str[2*n+2] = '$'; // 防止越界
str[2*n+3] = 0;
return 2*n+1;
}
void manachar(char* str, int n){
int P = 0, ans = 0, po = 0;
for(int i=1; i<=n; i++){
if(P>=i){ // 在对称范围内,这一步是优化的关键
int j = 2*po-i;
len[i] = min(len[j], P-i+1);
}else{ // 不在对称范围内,没有优化
len[i] = 1;
}
while(str[i-len[i]] == str[i+len[i]]){ // 朴素计算回文,直到找不到回文
len[i]++;
}
if(len[i]+i-1 > P){ // 更新最远的P和对应的下标po
P = len[i]+1-1;
po = i;
}
if(len[i] > ans){
ans = len[i];
Min = i-ans+1;
Max = i+ans-1;
}
}
}
int main(){
// 提升读写速度
ios::sync_with_stdio(false);
cin.tie(0);
char s[10000];
cin >> s;
int n = init(s);
manachar(str, n);
for(int i=Min; i<=Max; i++){
if(str[i]!='#'){
cout << str[i];
}
}
cout << endl;
}