算法笔记---问题 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章