Leetcode 最长回文子串 最长回文子序列

这篇博客介绍了如何使用动态规划解决最长回文子串和最长回文子序列的问题。作者通过LeetCode上的题目516和5,展示了两种不同情况下的解题思路,强调了不能简单地将回文问题转化为最长公共子串或子序列问题。代码中详细注释了动态规划数组的初始化和状态转移方程,对于理解此类问题的解决方法非常有帮助。
摘要由CSDN通过智能技术生成

今天写了最长回文子串和最长回文子序列,有必要来记录一下这一类问题.
我觉得这类问题和最长公共子串和最长公共子序列有些相似,当然都是用dp的思想.
但是,*肯定不能通过用逆转串来转化为最长公共子串和最长公共子序列 *来解决问题.
Leetcode516 最长回文子序列(已经注释非常清晰)

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int dp[s.size()][s.size()];
        /*
         *dp[i][j]代表 以s[i]-s[j] 的最长回文子序列长度
         *s[i]==s[j]&&J-I!=1 dp[i][j]=dp[i+1][j-1]+2
         *s[i]==s[j]&&J-I==1 dp[i][j]=2
         *s[i]!=s[j] dp[i][j]=max(dp[i+1][j],dp[i][j-1])
         */
         memset(dp,0,sizeof(dp));
         for(int i=0;i<s.size();i++) dp[i][i]=1;
         int len=2;
         for(;len<=s.size();len++){
             for(int i=0;i+len-1<s.size();i++){
                 int j=i+len-1;//终点
                 //cout<<i<<" "<<j<<endl;
                 if(s[i]==s[j]){
                     if(len==2) dp[i][j]=2;
                     else dp[i][j]=dp[i+1][j-1]+2;
                 }else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
             }
         }
        //  for(int i=0;i<s.size();i++){
        //      for(int j=0;j<s.size();j++) cout<<dp[i][j]<<" ";
        //      cout<<endl;
        //  }
         return dp[0][s.size()-1];
    }
};

Leetcode5.最长回文子串(已经注释非常清晰)

class Solution {
public:
    string longestPalindrome(string s) {
        int dp[s.size()][s.size()];
        memset(dp,0,sizeof(dp));
        /*
         *dp[i][j] 代表以s[i]开始s[j]结束的子串是否为回文串
         *0代表不是
         *1代笔是
        */
        int res=-1;
        int index1=0;
        int index2=0;
        for(int i=0;i<s.size();i++) dp[i][i]=1;//长度为1的子串必是回文字符串
        int len=2;//类似于矩阵连乘 对角线开始 然后根据len确定起点和终点
        for(;len<=s.size();len++){//执行s.size()-1次(可以自己画图推)
            for(int i=0;i+len-1<s.size();i++){
                int j=i+len-1;//i 代表起点 j代表终点
                if(s[i]!=s[j]) dp[i][j]=0;
                else{
                    if(j-i!=1) dp[i][j]=dp[i+1][j-1];
                    else dp[i][j]=1;//如果j=i+1 则直接等于1
                }
                if(dp[i][j]==1){
                    if(res<len){//比较长度 记录下表
                        res=len;
                        index1=i;
                        index2=j;
                    }
                }
            }
        }
        return s.substr(index1,index2-index1+1);
    }
};

Leetcode647.回文子串(该题与上题思路相同,只需要统计一下dp数组里1的个数即可)

class Solution {
public:
    int countSubstrings(string s) {
        int dp[s.size()][s.size()];
        memset(dp,0,sizeof(dp));
        /*
         *dp[i][j] 代表以s[i]开始s[j]结束的子串是否为回文串
         *0代表不是
         *1代笔是
        */
        //int index1=0;
       // int index2=0;
        for(int i=0;i<s.size();i++) dp[i][i]=1;//长度为1的子串必是回文字符串
        int res= s.size();
        int len=2;//类似于矩阵连乘 对角线开始 然后根据len确定起点和终点
        for(;len<=s.size();len++){//执行s.size()-1次(可以自己画图推)
            for(int i=0;i+len-1<s.size();i++){
                int j=i+len-1;//i 代表起点 j代表终点
                if(s[i]!=s[j]) dp[i][j]=0;
                else{
                    if(j-i!=1) dp[i][j]=dp[i+1][j-1];
                    else dp[i][j]=1;//如果j=i+1 则直接等于1
                }
                if(dp[i][j]==1){
                        res++;
                }
            }
        }
        return res;
    }
};

~~end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值