代码随想录|day57|动态规划part17● 647. 回文子串 ● 516.最长回文子序列● 动态规划总结篇

647. 回文子串

链接:代码随想录

动态规划解决的经典题目,如果没接触过的话,别硬想 直接看题解

 

 做法一:暴力遍历

class Solution {
//普通做法,暴力遍历,判断是否回文
public:
    int num=0;
    int countSubstrings(string s) {
        int n=s.size();
        for(int i=0;i<n;i++)
        {
            is_huiwen(i,i,s,n);
            is_huiwen(i,i+1,s,n);
        }
        return num;
        



    }
    
    void is_huiwen(int left,int right,string &s,int n)
    {
        while(left>=0 && right<n &&s[left]==s[right])
        {
           num++;   
            left--;
            right++;
        }

    }
};

动态规划做法,看了答案。

难点在于递推顺序,以及递推公式的构建和理解。

dp[i][j]相比前面的一些跟子序列、编辑距离相关的做法,取消了第0行第0列,dp[i][j]本身代表s[i...j]左闭右闭字符串是否为回文字符串。

 以字符串"abdba"为例:

class Solution {
/*动态规划,比较难以理解,建立在答案之上。
遍历顺序是从左下角开始的,也需要注意。
老实说,我感觉我理解了,能跟着老师思路顺下来,但是自己
想不到。

*/
public:
    int countSubstrings(string s) {

        int n=s.size();
        int cnt=0;//记录回文串个数
        //定义
        vector<vector<bool>>dp(n,vector<bool>(n,false));
        //初始化
        for(int i=0;i<n;i++)
        {
            dp[i][i]=true;
        }
        for(int i=n-1;i>=0;i--)
        {
            for(int j=i;j<n;j++)
            {
                if(s[i]!=s[j])
                {
                    dp[i][j]=false;
                }
                else
                {
                    if(j-i<=1)
                    {
                      dp[i][j]=true;
                      cnt++;
                    }
                    else
                    {
                        dp[i][j]=dp[i+1][j-1];
                        if(dp[i][j]==true)
                        {
                            cnt++;
                        }
                    }

                }
            }
        }

        //打印递推的数组
        /*for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }*/
        return cnt;

    }
};

516.最长回文子序列

647. 回文子串,求的是回文子串,而本题要求的是回文子序列, 大家要搞清楚两者之间的区别。

链接:代码随想录

 答案这里没有想到。感觉理解的不是很透彻。

class Solution {
/*
这个同时结合了最长公共子序列和回文子串的感觉!真神奇。
dp递推公式还是相当于没推理出来
*/
public:
    int longestPalindromeSubseq(string s) {
        int n=s.size();
        vector<vector<int>>dp(n,vector<int>(n,0));
        for(int i=0;i<n;i++)
        {
            dp[i][i]=1;
        }
        for(int i=n-2;i>=0;i--)
        {
            for(int j=i+1;j<n;j++)
            {
                if(s[i]==s[j])
                {
                    dp[i][j]=dp[i+1][j-1]+2;
                }
                else
                {
                    dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
                }
            }
        }
        return dp[0][n-1];


    }
};

动态规划总结篇。留到周末看。

代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值