dp——LeetCode5.最长回文子串

问题描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

示例 2:

输入: “cbbd”
输出: “bb”

问题分析

对于字符串数组s,用dp[i][j]判断从s[i]到s[j]是否是回文串,如果是,dp[i][j]为1,如果不是回文串,dp[i][j]为0。

则有动态方程dp[i][j]=dp[i+1][j-1]&&(s[i]==s[j]) ,j>=i+2
例如,如果"aba"是回文串,那么"xabax"也是会回文串。

特别的,当j ==i时,也视为回文串,即dp[i][i]=1,例如单个字母a。
当j ==i+1时,即dp[i][i+1]=(s[i]==s[j])

实质上这就是一个完善二维表的过程,二维表的长和宽是字符串的长度,主对角线全部为1,然后以主对角线斜向上逐步完善上三角,在完善过程中,找到满足条件的最大回文子串,当上三角完成后,即可输出结果。

代码实现

假如代码实现多组输入,先输入一个m,决定输入字符串的个数。

#include <bits/stdc++.h>

using namespace std;

const int MAX=1010;
int dp[MAX][MAX];

int main()
{
    
    
    int m;
    string s,ans;
    cin>>m;
    while(m--)
    {
    
    
        cin>>s;
        ans="";   
        int n=s.size();
        for(int k=0;k<n;k++)  //这是要循环n次,实现从主对角斜向上完善上三角矩阵。
          for(int i=0;i+k<n;i++){
    
     //i和k的下标都从0开始是最好的,见下面解析
            int j=i+k;
            if(k==0)  dp[i][i]=1;
            else if(k==1) dp[i][j]=s[i]==s[j];
            else dp[i][j]=dp[i+1][j-1]&&s[i]==s[j];
            if(dp[i][j]&&k+1>ans.size()){
    
    
                ans=s.substr(i,k+1);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

问题总结

1.string字符串赋空值,好像不能像java一样,直接s=null,需要这样 s="",让字符串等于空字符串。
2.string字符串的取子串substr函数,str.substr(pos,len),返回从pos开始的长度为len的string字符串。
3.i 的下标不能从1开始,本来打算i从1到n,即dp表的第0行不要,完成从第一行到第n行的上三角,但是发现了错误,那样的话动态方程也要改变了,变成dp[i][j]=dp[i+1][j-1]&&(s[i-1]==s[j-1]),细品,dp数组时从1开始的,而字符串数组s是从0开始的。
4.同理,k的下标应该也从0开始,例如,当k=0时,对应的刚好是主对角线,当k等于1时,对应的是主对角线上移的对角线。

猜你喜欢

转载自blog.csdn.net/HangHug_L/article/details/108550360