dp子序列

718. 最长重复子数组 - 力扣(LeetCode)

暴力法

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        int res = 0;
        for (int i = 0; i < nums1.size(); i++) {
            for (int j = 0; j < nums2.size(); j++) {
                int k = 0, len = 0;
                while (nums1[i + k] == nums2[j + k]&&i+k<nums1.size()&&j+k<nums2.size()) {
                    k++;
                    len++;
                }
                res = max(res, len);
            }
        }
        return res;
    }
};

while中的条件一定要写完整,避免数组越界。每次都错

300. 最长递增子序列 - 力扣(LeetCode)

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

二层循环条件是j<i,每次都错。

674. 最长连续递增序列 - 力扣(LeetCode)

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        vector<int> dp(nums.size()+1,1);
        int res=1;
        for(int i=1;i<nums.size();i++){
            if(nums[i]>nums[i-1]){
                dp[i]=dp[i-1]+1;
                res=max(res,dp[i]);
            } 
        }
        return res;
    }
};

718. 最长重复子数组 - 力扣(LeetCode)

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        int res=0;
        for(int i=1;i<=nums1.size();i++){
            for(int j=1;j<=nums2.size();j++){
               if(nums1[i-1]==nums2[j-1]){
                dp[i][j]=dp[i-1][j-1]+1;
                res=max(res,dp[i][j]);
               }
            }
        }
        return res;
    }
};

dp[i][j]表示的是以i-1,j-1结尾的最长重复子数组,所以if(nums1[i-1]==nums2[j-1]);

所以避免了初始化,因为dp[i][0]和dp[0][j]表示的就是-1和i-1,j-1的关系,没有意义,自动初始化为0.如果定义 dp[i][j]为 以下标i为结尾的A,和以下标j 为结尾的B,那么 第一行和第一列毕竟要进行初始化,如果nums1[i] 与 nums2[0] 相同的话,对应的 dp[i][0]就要初始为1, 因为此时最长重复子数组为1。 nums2[j] 与 nums1[0]相同的话,同理。

1143. 最长公共子序列 - 力扣(LeetCode)

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size()+1,vector<int>(text2.size()+1,0));
        int res=0;
        for(int i=1;i<=text1.size();i++){
            for(int j=1;j<=text2.size();j++){
                if(text1[i-1]==text2[j-1]){
                    dp[i][j]=dp[i-1][j-1]+1;
                    res=max(res,dp[i][j]);
                }
                else{
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                    res=max(res,dp[i][j]);
                }
            }
        }
        return res;
    }
};

1035. 不相交的线 - 力扣(LeetCode)

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        int res=0;
        for(int i=1;i<=nums1.size();i++){
            for(int j=1;j<=nums2.size();j++){
                if(nums1[i-1]==nums2[j-1]){
                    dp[i][j]=dp[i-1][j-1]+1;
                    res=max(res,dp[i][j]);
                }
                else{
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                    res=max(res,dp[i][j]);
                }
            }
        }
        return res;
    }
};

和上题一样

53. 最大子数组和 - 力扣(LeetCode)

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

392. 判断子序列 - 力扣(LeetCode)

class Solution {
public:
    bool isSubsequence(string s, string t) {
        vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));
        int res=0;
        for(int i=1;i<=s.size();i++){
            for(int j=1;j<=t.size();j++){
                if(s[i-1]==t[j-1]){
                    dp[i][j]=dp[i-1][j-1]+1;
                    res=max(res,dp[i][j]);
                }
                else{
                    dp[i][j]=dp[i][j-1];
                    res=max(res,dp[i][j]);
                }
            }
        }
        if(res==s.size()) return 1;
        return 0;
    }
};

115. 不同的子序列 - 力扣(LeetCode)

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

583. 两个字符串的删除操作 - 力扣(LeetCode)

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
        for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
        for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
        for (int i = 1; i <= word1.size(); i++) {
            for (int j = 1; j <= word2.size(); j++) {
                if (word1[i - 1] == word2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
                }
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

72. 编辑距离 - 力扣(LeetCode)

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
        for(int i=0;i<=word1.size();i++) dp[i][0]=i;
        for(int i=0;i<=word2.size();i++) dp[0][i]=i;

        for(int i=1;i<=word1.size();i++){
            for(int j=1;j<=word2.size();j++){
                if(word1[i-1]==word2[j-1]){
                    dp[i][j]=dp[i-1][j-1];
                }
                else{
                    dp[i][j]=min({dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1});
                }
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

蓝桥杯2023年第十四届省赛真题-更小的数(区间DP)-优快云博客

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e3+10;
int dp[N][N];
int n;
string s;
int ans=0;
signed main()
{
  ios::sync_with_stdio(false);cin.tie(0);
  cin>>s;
  
  for(int len=2;len<=s.size();len++){
  	for(int i=0;i+len-1<s.size();i++){
  		int j=i+len-1;
  		if(s[i]>s[j]) dp[i][j]=1;
  		else if(s[i]<s[j]) dp[i][j]=0;
  		else dp[i][j]=dp[i+1][j-1];
  		ans+=dp[i][j];
	  }
  }
  cout<<ans;
  return 0;
}

再做子序列问题时候,如果枚举字符串两个端点答案不对,试试先枚举字符串长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值