题目描述
输入一个字符串,求出其中最长的回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同。如abba和yyxyy。在判断回文时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000,且占据单独的一行。应该输出最长的回文串,如果有多个,输出起始位置最靠左的。
输入
一行字符串,字符串长度不超过5000。
输出
字符串中的最长回文子串。
样例
输入:
Confuciuss say:Madam,I'm Adam.
输出:
Madam,I'm Adam
解题思路:
使用动态规划求解
dp[i][j] 表示字符串下标为 i 到下标为 j 的子串为回文子串。
注意:
1、需要将所有的空格,逗号之类的非字母的字符去掉
2、需要将所有字符都变为小写或者大写
3、输出的时候,需要输出原来的字符串中的子串,即需要输出空格,逗号之类的字符。
4、若存在多个相同长度的回文子串,则需要输出最左边的子串,如abab,需要输出aba,而不是bab。
具体过程:
1、读入字符串
2、去掉字符串中的非字母的字符并将其他字母转换为小写(或者大写)
3、在转换的过程中,需要记录每个字母所对应的原来字符串中的位置
4、之后就是求解一个字符串中的最长回文子串,与 LeetCode5—最长回文子串 解法相同。
下面为AC代码:
/*
* @Description: Problem A 【字符串】最长回文子串
* @Author:
* @Date: 2020-05-04 16:13:17
* @LastEditTime: 2020-05-04 17:01:13
* @LastEditors: Please set LastEditors
*/
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int max_n = 5010;
string str; //表示输入的字符串
char temp[max_n];//表示去掉空格,逗号,以及都变成小写的字符串
int dp[max_n][max_n];//dp[i][j] 表示字符串下标为 i 到下标为 j 是回文串
int index[max_n];//表示存储temp字符串下标在str中的本来的位置,方便输出打印逗号以及空格
int main(){
//cin>>str;//因为输入有空格,故使用 getline
while(getline(cin,str)){
int j = 0; //表示temp数组的下标
for (int i = 0; i < str.size(); i++)
{
if (str[i] >= 'a' && str[i] <= 'z')
{
temp[j] = str[i];
index[j] = i;
j++;
}
if (str[i] >= 'A' && str[i] <= 'Z')
{
//temp[j] = str[i] + 32;//大写变成小写
temp[j] = tolower(str[i]); //两种方法都可以
index[j] = i;
j++;
}
}
//此时temp数组中存放的都是小写字母
//下面用正常的求解最长回文子串的解法即可
int start = 0;
int max_length = 1;//表示最长回文字符串的长度
int max_current = 1;//表示当前最长回文字符串的长度
fill(dp[0], dp[0] + max_n * max_n, 0);
int len = j; // //len 表示 temp 数组的长度
for (int i = 0; i < len; i++)
{
dp[i][i] = 1; //表示每一个字符都是一个回文串
if (i < len - 1)
{
if (temp[i] == temp[i + 1])
{
dp[i][i + 1] = 1;
max_length = 2;
if(max_length > max_current){//保证如果有多个相同长度的回文串,输出最左边的回文串
start = i;
max_current = max_length;
}
}
}
}
//下面为状态转换方程
for (int L = 3; L <= len; L++)
{ //遍历所有长度的子串
for (int i = 0; i + L - 1 < len; i++)
{
int j = i + L - 1; //表示子串的右端点
if (temp[i] == temp[j] && dp[i + 1][j - 1] == 1)
{
dp[i][j] = 1;
max_length = L;
if(max_length > max_current){ //保证如果有多个相同长度的回文串,输出最左边的回文串
start = i;
max_current = max_length;
}
}
}
}
//输出最长回文子串
for (int i = index[start]; i <= index[start + max_current - 1]; i++)
{
cout << str[i];
}
cout << endl;
}
//system("pause");
return 0;
}