字符串中的各种子序列的问题

本文详细解析了多种经典的动态规划问题及其解决方案,包括最长公共子串、最长公共子序列、子序列计数、最长上升子序列等,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.字符串的最长公共字串(string s,string t)

 dp[i][j] = (s[i] == s[j] ? dp[i-1][j-1] + 1:0);

2.字符串的最长公共子序列

dp[i][j] = (s[i]==s[j]?dp[i-1][j-1]+1:max(dp[i-1][j],dp[i][j-1]))

3.求s中和t一样的子序列的个数 (leetcode115 Distinct Subsequences)

dp[i][j] = dp[i-1][j] + (s[i]==s[j]?dp[i-1][j-1]:0)

class Solution {
public:
    int numDistinct(string s, string t) {
        int len1 = s.length();
        int len2 = t.length();
        vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
        for (int i=0;i<=len1;i++) dp[i][0] = 1;
        for (int i=1;i<=len1;i++)
        {
            for(int j=1;j<=len2;j++)
            {
                if(s[i-1]==t[j-1]) 
                {
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-1];
                }
                else dp[i][j] = dp[i-1][j];
            }
        }
        return dp[len1][len2];
        
    }
};

4.最长上升子序列(LIS)

方法1:普通dp  O(n^2)

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n,1);
        int ans = 0;
        for(int i=0;i<n;i++)
        {
            for(int j=i;j>=0;j--)
            {
                if(nums[i]>nums[j]) 
                {
                    dp[i]=max(dp[i],dp[j]+1);
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            ans = ans<dp[i]?dp[i]:ans;
        }
        return ans;
    }
};

方法2:二分查找+贪心

(待补充)

5.最长上升子序列的数量  leetcode673 Number of Longest Increasing Subsequence

class Solution {
public:
    int findNumberOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n,1),lens(n,1); //dp记录i结尾的最长上升子序列长度,lens记录i结尾的最长长度上升子序列的数量
        int maxlen = 1;
        for(int i=1;i<n;i++)
        {
            for(int j=i;j>=0;j--)
            {
                if(nums[i]>nums[j]&&dp[j]+1>dp[i])
                {
                    dp[i] = dp[j] + 1;
                    lens[i] = lens[j];
                }
                else if(nums[i]>nums[j]&&dp[i]==dp[j]+1)
                {
                    lens[i] = lens[i] + lens[j];
                }
            }
            maxlen = max(maxlen,dp[i]);
        }
        int ans = 0;
        for(int i=0;i<n;i++)
        {
            if(dp[i]==maxlen) ans+=lens[i];
        }
        return ans;
    }
};

6.最长摇摆子序列 376. Wiggle Subsequence

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if(n==0) return 0;
        int flag = -1,maxlen = 1,pre=0;
        pre = nums[0];
        for(int i=0;i<n;i++)
        {
            if(nums[i]==pre) continue;
            if(flag != nums[i]>pre)
            {
                flag = nums[i] > pre;
                maxlen++;
            }
            pre = nums[i];
        }
        return maxlen;
    }
};

7.730. Count Different Palindromic Subsequences

8.128. Longest Consecutive Sequence

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值