題目描述
輸入一個字符串,求出其中最長的迴文子串。子串的含義是:在原串中連續出現的字符串片段。迴文的含義是:正着看和倒着看相同。如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;
}