算法笔记—动态规划
1137. 第 N 个泰波那契数 - 力扣(LeetCode)
class Solution {
public:int tribonacci(int n) {if(n==0) return 0;if(n==1||n==2) return 1;vector<int> dp(4);//初始化dp[0]=0; dp[1]=1; dp[2]=1;for(int i=3;i<n+1;i++){//滚动数组优化需要循环dp[i%4]=dp[(i-1)%4]+dp[(i-2)%4]+dp[(i-3)%4];}return dp[n%4];}
};
面试题 08.01. 三步问题 - 力扣(LeetCode)
class Solution {
public:int waysToStep(int n) {const int MOD=1e9+7;if(n==1) return 1;if(n==2) return 2;if(n==3) return 4;int a=1; int b=2; int c=4; int d=0;for(int i=4;i<=n;i++){d=((a+b)%MOD+c)%MOD;a=b; b=c; c=d;}return d;}
};
746. 使用最小花费爬楼梯 - 力扣(LeetCode)
class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {int n=cost.size();if(n<=1) return 0;vector<int> dp(n+1);dp[0]=0;dp[1]=0;for(int i=2;i<n+1;i++){dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);}return dp[n];}
};
91. 解码方法 - 力扣(LeetCode)
class Solution {
public:int numDecodings(string s) {int n=s.size();vector<int> dp(n,0);dp[0]=s[0]!='0';if(n==1) return dp[0];//初始化下标1if('0'<s[1]&&s[1]<='9') dp[1]+=dp[0];int a=s[0]-'0'; int b=s[1]-'0';if(10<=a*10+b&&a*10+b<=26) dp[1]++;for(int i=2;i<n;i++){if('0'<s[i]&&s[i]<='9') dp[i]+=dp[i-1];int c=s[i-1]-'0'; int d=s[i]-'0';if(10<=c*10+d&&c*10+d<=26&&dp[i-2]) dp[i]+=dp[i-2];}for(int &val:dp){cout<<val<<endl;}return dp[n-1];}
};
62. 不同路径 - 力扣(LeetCode)
class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m+1,vector<int>(n+1,0)); dp[1][0]=1;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){dp[i][j]=dp[i-1][j]+dp[i][j-1];}}return dp[m][n];}
};
63. 不同路径 II - 力扣(LeetCode)
class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m=obstacleGrid.size(); int n=obstacleGrid[0].size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));dp[1][0]=1;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(obstacleGrid[i-1][j-1]!=1)dp[i][j]=dp[i-1][j]+dp[i][j-1];}}return dp[m][n];}
};
LCR 166. 珠宝的最高价值 - 力扣(LeetCode)
class Solution {
public:int jewelleryValue(vector<vector<int>>& frame) {int m=frame.size(); int n=frame[0].size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){dp[i][j]=max(dp[i-1][j],dp[i][j-1])+frame[i-1][j-1];}}return dp[m][n];}
};
931. 下降路径最小和 - 力扣(LeetCode)
class Solution {
public:int minFallingPathSum(vector<vector<int>>& matrix) {//建表int m=matrix.size(); int n=matrix[0].size();vector<vector<int>> dp(m+1,vector<int>(n+2,INT_MAX));//初始化for(int i=0;i<=n+1;i++){dp[0][i]=0;}//填表for(int i=1;i<=m;i++){for(int j=1;j<n+1;j++){dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i-1][j+1]))+matrix[i-1][j-1];//***1***注意dp的下标和数据数组的下标对应起来,**2**初始化要满足依靠初始的状态填表正确}}int ret=INT_MAX;for(int i=1;i<n+1;i++){ret=min(dp[m][i],ret);}return ret;}
};
64. 最小路径和 - 力扣(LeetCode)
class Solution {
public:int minPathSum(vector<vector<int>>& grid) {//建表int m=grid.size(); int n=grid[0].size();vector<vector<int>> dp(m+1,vector<int>(n+1,INT_MAX));//初始化dp[0][1]=0;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i-1][j-1];}}for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){cout<<dp[i][j]<<" ";}cout<<endl;}return dp[m][n];}
};
174. 地下城游戏 - 力扣(LeetCode)
class Solution {
public:int calculateMinimumHP(vector<vector<int>>& dungeon) {int m=dungeon.size(); int n=dungeon[0].size();vector<vector<int>> dp(m+1,vector<int>(n+1,INT_MAX));dp[m][n-1]=1;//依题意是 1,不是0;for(int i=m-1;i>=0;i--){for(int j=n-1;j>=0;j--){dp[i][j]=min(dp[i+1][j],dp[i][j+1])-dungeon[i][j];dp[i][j]=dp[i][j]<1?1:dp[i][j];//状态表示:骑士的血无法小于1}}return dp[0][0]<1?1:dp[0][0];}
};
面试题 17.16. 按摩师 - 力扣(LeetCode)
class Solution {
public:int massage(vector<int>& nums) {int n=nums.size();if(n==0) return 0;vector<int> f(n);vector<int> g(n);f[0]=nums[0];for(int i=1;i<n;i++){g[i]=max(f[i-1],g[i-1]);f[i]=g[i-1]+nums[i];// cout<<g[i]<<" "<<f[i]<<endl;}return g[n-1]>f[n-1]?g[n-1]:f[n-1];}
};
213. 打家劫舍 II - 力扣(LeetCode)
class Solution {
public:int rob(vector<int>& nums) {int n=nums.size();return max(nums[0]+rob_1(nums,2,n-2),rob_1(nums,1,n-1));}int rob_1(vector<int>& nums,int left,int right){if(left>right) return 0;//**1**数据不满足范围,那么需要返回0int n=nums.size();vector<int> f(n);vector<int> g(n);f[left]=nums[left];for(int i=left+1;i<=right;i++){g[i]=max(g[i-1],f[i-1]);f[i]=g[i-1]+nums[i];}return g[right]>f[right]?g[right]:f[right];}
};
740. 删除并获得点数 - 力扣(LeetCode)
class Solution {
public:int deleteAndEarn(vector<int>& nums) {int hash[10001]={0};for(int &val:nums){hash[val]+=val;}int f[10001];int g[10001];f[0]=hash[0];for(int i=1;i<10001;i++){g[i]=max(g[i-1],f[i-1]);f[i]=g[i-1]+hash[i];}return g[10000]>f[10000]?g[10000]:f[10000];}
};
LCR 091. 粉刷房子 - 力扣(LeetCode)
class Solution {
public:int minCost(vector<vector<int>>& costs) {int m=costs.size(); int n=costs[0].size();vector<vector<int>> dp(m+1,vector<int>(3,0));for(int i=1;i<=m;i++){dp[i][0]=min(dp[i-1][1],dp[i-1][2])+costs[i-1][0];//***1***初始化要满足递推为正确dp[i][1]=min(dp[i-1][0],dp[i-1][2])+costs[i-1][1];//***2***下标要映射正确dp[i][2]=min(dp[i-1][1],dp[i-1][0])+costs[i-1][2];}int ret=INT_MAX;for(int i=0;i<3;i++){ret=min(ret,dp[m][i]);}return ret;}
};
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)
class Solution {
public:int maxProfit(vector<int>& prices, int fee) {const int n=prices.size();int f[n]; int g[n];f[0]=-prices[0]; g[0]=0;for(int i=1;i<n;i++){f[i]=max(g[i-1]-prices[i],f[i-1]);g[i]=max(f[i-1]+prices[i]-fee,g[i-1]);}return g[n-1]; }
};
123. 买卖股票的最佳时机 III - 力扣(LeetCode)
class Solution {
public:int maxProfit(vector<int>& prices) {int n=prices.size();int INF=0x3f3f3f3f;vector<vector<int>> f(n,vector<int>(3,-INF));vector<vector<int>> g(n,vector<int>(3,-INF));f[0][0]=-prices[0]; g[0][0]=0;//g[0][0],j=0表示初始状态处于无股票状态,没有买入和卖出,f[0][0];j=0表示第一次买入for(int i=1;i<n;i++){for(int j=0;j<3;j++){f[i][j]=max(f[i-1][j],g[i-1][j]-prices[i]);g[i][j]=g[i-1][j];if(j-1>=0)g[i][j]=max(g[i-1][j],f[i][j-1]+prices[i]);}}int ret=0;for(int i=0;i<3;i++){ret=max(ret,g[n-1][i]);}return ret;}
};
188. 买卖股票的最佳时机 IV - 力扣(LeetCode)
class Solution {
public:int maxProfit(int k, vector<int>& prices) {int n=prices.size();int INF=0x3f3f3f3f;//优化;k=min(k,n/2);//最多交易n/2次vector<vector<int>> f(n,vector<int>(k+1,-INF));vector<vector<int>> g(n,vector<int>(k+1,-INF));f[0][0]=-prices[0]; g[0][0]=0;for(int i=1;i<n;i++){//***2***从第2天开始for(int j=0;j<k+1;j++){f[i][j]=max(f[i-1][j],g[i-1][j]-prices[i]);g[i][j]=g[i-1][j];if(j-1>=0)g[i][j]=max(g[i-1][j],f[i-1][j-1]+prices[i]);}}int ret=0;for(int i=0;i<k+1;i++){ret=max(ret,g[n-1][i]);}return ret;}
};
53. 最大子数组和 - 力扣(LeetCode)
class Solution {
public:int maxSubArray(vector<int>& nums) {int n=nums.size();//建表vector<int> dp(n+1,0);const int INF=0x3f3f3f3f;int ret=-INF;for(int i=1;i<=n;i++){dp[i]=max(nums[i-1],dp[i-1]+nums[i-1]);ret=max(ret,dp[i]);}return ret;}
};
918. 环形子数组的最大和 - 力扣(LeetCode)
class Solution {
public:int maxSubarraySumCircular(vector<int>& nums) {int n=nums.size();vector<int> f(n+1);vector<int> g(n+1);int fmax=INT_MIN; int gmin=INT_MAX; int sum=0;//用来标记全为负数的情况for(int i=1;i<=n;i++){int x=nums[i-1];f[i]=max(f[i-1]+nums[i-1],nums[i-1]);fmax=max(fmax,f[i]);g[i]=min(g[i-1]+nums[i-1],nums[i-1]);gmin=min(gmin,g[i]);sum+=x;}return sum==gmin?fmax:max(fmax,sum-gmin);}
};
152. 乘积最大子数组 - 力扣(LeetCode)
class Solution {
public:int maxProduct(vector<int>& nums) {int n=nums.size();vector<int> f(n+1);vector<int> g(n+1);//**1**初始化f[0]=1; g[0]=1;int ret=INT_MIN;for(int i=1;i<=n;i++){f[i]=max(nums[i-1],max(f[i-1]*nums[i-1],g[i-1]*nums[i-1]));g[i]=min(nums[i-1],min(f[i-1]*nums[i-1],g[i-1]*nums[i-1]));ret=max(ret,f[i]); }return ret;}
};
1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)
class Solution {
public:int getMaxLen(vector<int>& nums) {int n=nums.size();vector<int> f(n+1);vector<int> g(n+1);int ret=INT_MIN;for(int i=1;i<n+1;i++){if(nums[i-1]==0){//**3**比较符号不要写成=f[i]=0; g[i]=0;}else if(nums[i-1]<0){f[i]=g[i-1]==0?0:g[i-1]+1;//**1**注意逻辑关系:负数*负数=正数g[i]=f[i-1]+1;//正数*负数=负数}else if(nums[i-1]>0){f[i]=f[i-1]+1;g[i]=g[i-1]==0?0:g[i-1]+1;}cout<<f[i]<<" "<<g[i]<<endl;ret=max(ret,f[i]);}return ret;}
};
413. 等差数列划分 - 力扣(LeetCode)
class Solution {
public:int numberOfArithmeticSlices(vector<int>& nums) {int n=nums.size();vector<int> dp(n);int sum=0;for(int i=2;i<n;i++){dp[i]=nums[i]+nums[i-2]==2*nums[i-1]?dp[i-1]+1:0;sum+=dp[i];}return sum;}
};
978. 最长湍流子数组 - 力扣(LeetCode)
class Solution {
public:int maxTurbulenceSize(vector<int>& arr) {int n=arr.size();vector<int> f(n,1);vector<int> g(n,1);int ret=1;for(int i=1;i<n;i++){if(arr[i]>arr[i-1]){f[i]=g[i-1]+1;}else if(arr[i]<arr[i-1]){g[i]=f[i-1]+1;}ret=max(ret,max(g[i],f[i]));}return ret;}
};
139. 单词拆分 - 力扣(LeetCode)
class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> hash;for(int i=0;i<wordDict.size();i++){hash.insert(wordDict[i]);}int n=s.size();vector<bool> dp(n+1,false);dp[0]=true;for(int i=1;i<n+1;i++){for(int j=0;j<i;j++){// cout<<s.substr(j,i-j)<<" ";//**1**对应首位下标改变,长度不变。if(dp[j]&&hash.count(s.substr(j,i-j)))dp[i]=true;cout<<endl;}}return dp[n];}
};
467. 环绕字符串中唯一的子字符串 - 力扣(LeetCode)
class Solution {
public:int findSubstringInWraproundString(string s) {int n=s.size();vector<int> dp(n,1);for(int i=1;i<n;i++)if(s[i]==s[i-1]+1||(s[i]=='a'&&s[i-1]=='z'))dp[i]=dp[i-1]+1;int hash[26];for(int i=0;i<n;i++){hash[s[i]-'a']=max(hash[s[i]-'a'],dp[i]);}int sum=0;for(int i=0;i<26;i++){sum+=hash[i];}return sum;}
};
300. 最长递增子序列 - 力扣(LeetCode)
class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n=nums.size();vector<int> dp(n,1);int ret=1;for(int i=1;i<n;i++){for(int j=0;j<i;j++){if(nums[i]>nums[j])dp[i]=max(dp[i],dp[j]+1);}ret=max(ret,dp[i]);}return ret;}
};
376. 摆动序列 - 力扣(LeetCode)
class Solution {
public:int wiggleMaxLength(vector<int>& nums) {int n=nums.size();vector<int> g(n,1);vector<int> f(n,1);int ret=1;for(int i=1;i<n;i++){for(int j=0;j<i;j++){if(nums[i]>nums[j]) f[i]=max(g[j]+1,f[i]);if(nums[i]<nums[j]) g[i]=max(f[j]+1,g[i]);}ret=max(ret,max(g[i],f[i]));}return ret;}
};
673. 最长递增子序列的个数 - 力扣(LeetCode)
class Solution {
public:int findNumberOfLIS(vector<int>& nums) {int n=nums.size();vector<int> len(n,1),count(n,1);int retlen=1; int retcount=1;for(int i=1;i<n;i++){for(int j=0;j<i;j++){if(nums[i]>nums[j]){if(len[j]+1==len[i]){count[i]+=count[j];}else if(len[j]+1>len[i]){len[i]=len[j]+1;count[i]=count[j];}}}if(retlen<len[i]){retlen=len[i]; retcount=count[i];}else if(retlen==len[i]){retcount+=count[i];}}return retcount;}
};
646. 最长数对链 - 力扣(LeetCode)
class Solution {
public:int findLongestChain(vector<vector<int>>& pairs) {sort(pairs.begin(),pairs.end(),[](vector<int> a,vector<int> b){return a[0]<b[0]||(a[0]==b[0]&&a[1]<b[1]);});int n=pairs.size();int ret=1;vector<int> dp1(n,1);for(int i=1;i<n;i++){for(int j=0;j<i;j++){if(pairs[i][0]>pairs[j][1]) dp1[i]=dp1[j]+1;}ret=max(dp1[i],ret);}return ret;}
};
1218. 最长定差子序列 - 力扣(LeetCode)
class Solution {
public:int longestSubsequence(vector<int>& arr, int difference) {int n=arr.size();unordered_map<int,int> hash;hash[arr[0]]=1;int ret=1;for(int i=1;i<n;i++){hash[arr[i]]=hash[arr[i]-difference]+1;//**1**等差数组没有前缀,也要插入hash表中ret=max(ret,hash[arr[i]]); }return ret;}
};
873. 最长的斐波那契子序列的长度 - 力扣(LeetCode)
class Solution {
public:int lenLongestFibSubseq(vector<int>& arr) {int n=arr.size();unordered_map<int,int> hash;for(int i=0;i<n;i++){hash[arr[i]]=i;}vector<vector<int>> dp(n,vector<int>(n,2));int ret=2;for(int i=2;i<n;i++){for(int j=1;j<i;j++){int a=arr[i]-arr[j];if(a<arr[j]&&hash.count(a)){dp[j][i]=dp[hash[a]][j]+1;}ret=max(ret,dp[j][i]);}}return ret<3?0:ret;}
};
1027. 最长等差数列 - 力扣(LeetCode)
class Solution {
public:int longestArithSeqLength(vector<int>& nums) {int n=nums.size();unordered_map<int,int> hash;// hash[nums[0]]=0; hash[nums[1]]=1;hash[nums[0]]=0;vector<vector<int>> dp(n,vector<int>(n,2));int ret=2;//任意两个数都可以构成等差数列for(int j=1;j<n;j++){for(int i=j+1;i<n;i++){int a=2*nums[j]-nums[i];//a可能有多个值,我们必须找到最右端的值,才是最大的,if(hash.count(a)){dp[j][i]=dp[hash[a]][j]+1;} ret=max(dp[j][i],ret); // cout<<dp[j][i]<<" ";}hash[nums[j]]=j;// cout<<endl;}return ret;}
};
446. 等差数列划分 II - 子序列 - 力扣(LeetCode)
class Solution {
public:int numberOfArithmeticSlices(vector<int>& nums) {int n=nums.size();unordered_map<long long,vector<int>> hash;//**2** long long因为推导等差数组前的值需要2*nums[j].vector<vector<int>> dp(n,vector<int>(n,0));for(int i=0;i<n;i++){hash[nums[i]].push_back(i);}int sum=0;for(int i=2;i<n;i++){for(int j=1;j<i;j++){long long a=(long long)2*nums[j]-nums[i];if(hash.count(a)){//***1**必须要先寻找,hash[a],相当于插入了for(int k:hash[a]){if(k<j) dp[j][i]+=dp[k][j]+1;else break;cout<<k<<" ";}}sum+=dp[j][i];}}return sum;}
};
647. 回文子串 - 力扣(LeetCode)
class Solution {
public:int countSubstrings(string s) {int n=s.size();vector<vector<bool>> dp(n,vector<bool>(n,false));int ret=0;for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){if(s[i]==s[j]){dp[i][j]=i+1<j?dp[i+1][j-1]:true; }else{dp[i][j]=false;}if(dp[i][j]==true) ret++;}}return }
};
5. 最长回文子串 - 力扣(LeetCode)
class Solution {
public:string longestPalindrome(string s) {int n=s.size();vector<vector<bool>> dp(n,vector<bool>(n,0));int len=0; int begin=0;for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){if(s[i]==s[j]){dp[i][j]=i+1<j?dp[i+1][j-1]:true;}if(dp[i][j]==true&&j-i+1>len){len=j-i+1; begin=i;}}}return s.substr(begin,len);}
};
1745. 分割回文串 IV - 力扣(LeetCode)
class Solution {
public:bool checkPartitioning(string s) {int n=s.size();vector<vector<bool>> dp(n,vector<bool>(n,false));for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){if(s[i]==s[j]){dp[i][j]=i+1<j?dp[i+1][j-1]:true;}}}for(int j=1;j<n;j++){for(int i=j+1;i<n;i++){if(dp[0][j-1]&&dp[j][i-1]&&dp[i][n-1]) return true;}}return false;}
};
132. 分割回文串 II - 力扣(LeetCode)
class Solution {
public:int minCut(string s) {int n=s.size();vector<vector<bool>> dp(n,vector<bool>(n,false));for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){if(s[i]==s[j])dp[i][j]=i+1<j ? dp[i+1][j-1]:true;}}int ret=INT_MAX;vector<int> dp1(n,INT_MAX);for(int i=0;i<n;i++){if(dp[0][i]) dp1[i]=0;else{for(int j=0;j<i;j++){if(dp[j+1][i]) dp1[i]=min(dp1[j]+1,dp1[i]);}}}return dp1[n-1];//**根据状态表示返回}
};
516. 最长回文子序列 - 力扣(LeetCode)
class Solution {
public:int longestPalindromeSubseq(string s) {int n=s.size();vector<vector<int>> dp(n,vector<int>(n,0));for(int i=n-1;i>=0;i--){dp[i][i]=1;for(int j=i+1;j<n;j++){if(s[i]==s[j])dp[i][j]=dp[i+1][j-1]+2;//i+1=j时dp[i+1][j-1]=0,不变else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);}}return dp[0][n-1];}
};
1312. 让字符串成为回文串的最少插入次数 - 力扣(LeetCode)
class Solution {
public:int minInsertions(string s) {int n=s.size();vector<vector<int>> dp(n,vector<int>(n,0));for(int i=n-1;i>=0;i--){for(int j=i+1;j<n;j++){if(s[i]==s[j]) 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[0][n-1];}
};
1143. 最长公共子序列 - 力扣(LeetCode)
class Solution {
public:int longestCommonSubsequence(string text1, string text2) {int m=text1.size(); int n=text2.size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));string s1=" "+text1; string s2=" "+text2;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(s1[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1;else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);}}return dp[m][n];}
};
1035. 不相交的线 - 力扣(LeetCode)
class Solution {
public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {int m=nums1.size(); int n=nums2.size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));for(int i=1;i<m+1;i++){for(int j=1;j<n+1;j++){if(nums1[i-1]==nums2[j-1]) dp[i][j]=dp[i-1][j-1]+1;else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);}}return dp[m][n];}
};
115. 不同的子序列 - 力扣(LeetCode)
class Solution {
public:int numDistinct(string s, string t) {int ret=0;int m=s.size(); int n=t.size();int MOD=1e9+7;vector<vector<double>> dp(m+1,vector<double>(n+1,0));for(int j=0;j<=m;j++) dp[j][0]=1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){dp[j][i]+=dp[j-1][i];if(s[j-1]==t[i-1]) {//**2**写成是s[j-1]==t[i-1]// cout<<endl<<"j,i "<<j<<" "<<i<<" "<<"s[j-1]"<<s[j-1]<<" s[i-1]"<<s[i-1]<<endl;dp[j][i]+=dp[j-1][i-1];//**1**:+=不是=。}// cout<<dp[j][i]<<" ";}// cout<<endl<<"_____________";}return dp[m][n];}
};
44. 通配符匹配 - 力扣(LeetCode)
class Solution {
public:bool isMatch(string s, string p) {int n=s.size(); int m=p.size();vector<vector<bool>> dp(m+1,vector<bool>(n+1,false));s=' '+s; p=' '+p;dp[0][0]=true;for(int i=1;i<=m;i++){if(p[i]=='*')dp[i][0]=true;else break;}for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(p[i]=='*') dp[i][j]=dp[i-1][j]+dp[i][j-1];//**1**状态转移方程写成dp[i-1][j-1]+dp[i][j-1]else if(p[i]=='?'||p[i]==s[j]) dp[i][j]=dp[i-1][j-1];}}return dp[m][n];}
};
10. 正则表达式匹配 - 力扣(LeetCode)
class Solution {
public:bool isMatch(string s, string p) {int m=s.size(); int n=p.size();vector<vector<bool>> dp(m+1,vector<bool>(n+1,false));//**1**记得扩表s=' '+s; p=' '+p;dp[0][0]=true;for(int i=2;i<=n;i+=2) //初始化,结合题意,匹配空串,所以i=1,3,5,7,时,且i=奇数,这个奇数之前都是可以匹配的,也就是*,所以根据*之前必须匹配有效字符串所以必须是'.'或者a~zif(p[i]=='*') dp[0][i]=true;else break;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(p[j]=='*') dp[i][j]=dp[i][j-2]||((p[j-1]=='.'||s[i]==p[j-1])&&dp[i-1][j]);else dp[i][j]=(p[j]==s[i]||p[j]=='.')&&dp[i-1][j-1];}}return dp[m][n];}
};
97. 交错字符串 - 力扣(LeetCode)
class Solution {
public:bool isInterleave(string s1, string s2, string s3) {int m=s1.size(); int n=s2.size(); if(m+n!=s3.size()) return false;s1=' '+s1; s2=' '+s2; s3=' '+s3;//优化,滚动数组vector<bool> dp(n+1,false);dp[0]=true;for(int i=1;i<=n;i++){if(s2[i]==s3[i])dp[i]=true;else break; }for(int i=1;i<=m;i++){for(int j=0;j<=n;j++){if(j==0){dp[j]=s1[i]==s3[i+j]&&dp[j];}elsedp[j]=(s1[i]==s3[i+j]&&dp[j])||(s2[j]==s3[i+j]&&dp[j-1]);}}return dp[n];//normal// vector<vector<bool>> dp(m+1,vector<bool>(n+1,false));// dp[0][0]=true;// for(int i=1;i<=m;i++){// if(s1[i]==s3[i])// dp[i][0]=true;// else break; // }// for(int j=1;j<=n;j++){// if(s2[j]==s3[j])// dp[0][j]=true; // else break; // }// for(int i=1;i<=m;i++){// for(int j=1;j<=n;j++){// dp[i][j]=((s1[i]==s3[i+j])&&dp[i-1][j])||((s2[j]==s3[i+j])&&dp[i][j-1]);// }// }// return dp[m][n];}
};
712. 两个字符串的最小ASCII删除和 - 力扣(LeetCode)
class Solution {
public:int minimumDeleteSum(string s1, string s2) {int m=s1.size(); int n=s2.size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){dp[i][j]=max(dp[i-1][j],dp[i][j-1]);if(s1[i-1]==s2[j-1]){dp[i][j]=max(dp[i][j],dp[i-1][j-1]+s1[i-1]);}}}int sum=0;for(int val:s1) sum+=val;for(int val:s2) sum+=val;return sum-dp[m][n]-dp[m][n];}
};
718. 最长重复子数组 - 力扣(LeetCode)
class Solution {
public:int findLength(vector<int>& nums1, vector<int>& nums2) {int m=nums1.size(); int n=nums2.size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));int ret=0;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(nums1[i-1]==nums2[j-1])dp[i][j]=dp[i-1][j-1]+1; ret=max(ret,dp[i][j]); }}return ret;}
};