算法筆記---問題 A: 【字符串】最長迴文子串

題目描述

輸入一個字符串,求出其中最長的迴文子串。子串的含義是:在原串中連續出現的字符串片段。迴文的含義是:正着看和倒着看相同。如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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章