回文子串

GitHub跳转原题关系图返回列表

按长度和起点枚举子串,用动态规划递推判断并按要求输出全部回文子串。

OJ: noi_openjudge

题目 ID: ch0107-34

难度:普及/提高-

标签:动态规划字符串回文python

日期: 2026-07-30 23:01

题意

输出所有长度至少为 22 的回文子串,先按长度升序,再按起点升序。

思路

is_palindrome[left][right] 表示该闭区间是否回文。若两端字符相同,且中间区间也是回文,则当前区间回文;单字符对角线先设为真。外层按子串长度枚举、内层按起点枚举,天然满足输出顺序。

DP 状态示意

下表展示 abba 的关键状态,单元格表示对应子串是否回文:

子串 bb abba
两端字符相同
内部区间回文 单字符 bb
结果

先确认短区间,再扩展到更长区间,这正是状态依赖方向。

Python代码

python
import sys

text = input().strip()
length = len(text)
is_palindrome = [[False] * length for _ in range(length)]
answer = []

for index in range(length):
    is_palindrome[index][index] = True

for substring_length in range(2, length + 1):
    for start in range(length - substring_length + 1):
        end = start + substring_length - 1
        if text[start] == text[end] and (substring_length == 2 or is_palindrome[start + 1][end - 1]):
            is_palindrome[start][end] = True
            answer.append(text[start : end + 1])

sys.stdout.write("\n".join(answer))
if answer:
    sys.stdout.write("\n")

C++代码

cpp
#include <cstdio>
#include <cstring>

char s[1000];
char tmp[1000];

bool is_hui_wen(){
    int len =  strlen(tmp);
    int mid = len /2;
    int i,j;
    for (i=0;i<mid;i++){
        if( tmp[i] != tmp[len-i-1]){
            return false;
        }
    }
    return true;
}
int main(){
    scanf("%s",s+1);
    int len = strlen(s+1);
    int i,j;
    for(i=2;i<=len;i++){
        for (j=1;j<=len-i+1;j++){
            memset(tmp,0,sizeof(tmp));
            strncpy(tmp,s+j,i);
            //printf("%s\n",tmp);
            if( is_hui_wen())
                printf("%s\n",tmp);
        }
    }
    return 0;
}

复杂度

状态数为 O(n2)O(n^2),时间和空间复杂度均为 O(n2)O(n^2),不含输出本身。

总结

回文区间的两端相等与内部回文构成了标准区间 DP 递推。

代码

cpp
#include <cstdio>
#include <cstring>

char s[1000];
char tmp[1000];

bool is_hui_wen(){
    int len =  strlen(tmp);
    int mid = len /2;
    int i,j;
    for (i=0;i<mid;i++){
        if( tmp[i] != tmp[len-i-1]){
            return false;
        }
    }
    return true;
}
int main(){
    scanf("%s",s+1);
    int len = strlen(s+1);
    int i,j;
    for(i=2;i<=len;i++){
        for (j=1;j<=len-i+1;j++){
            memset(tmp,0,sizeof(tmp));
            strncpy(tmp,s+j,i);
            //printf("%s\n",tmp);
            if( is_hui_wen())
                printf("%s\n",tmp);
        }
    }
    return 0;
}

复杂度

总结