当前位置:   article > 正文

C++--两个数组的dp问题(2)

C++--两个数组的dp问题(2)

1.交错字符串  力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给定三个字符串 s1s2s3,请判断 s3 能不能由 s1 和 s2 交织(交错) 组成。

两个字符串 st 交织 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:

  • s = s1 + s2 + ... + sn
  • t = t1 + t2 + ... + tm
  • |n - m| <= 1
  • 交织s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...

提示:a + b 意味着字符串 ab 连接。

示例 1:

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出:true

示例 2:

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出:false

示例 3:

输入:s1 = "", s2 = "", s3 = ""
输出:true
  1. class Solution {
  2. public:
  3. bool isInterleave(string s1, string s2, string s3)
  4. {
  5. int n=s1.size();
  6. int m=s2.size();
  7. if(m+n!=s3.size())
  8. return false;
  9. s1=" "+s1;
  10. s2=" "+s2;
  11. s3=" "+s3;
  12. //初始化
  13. vector<vector<bool>> dp(n+1,vector<bool>(m+1));
  14. dp[0][0]=true;
  15. for(int j=1;j<=m;j++)
  16. {
  17. if(s2[j]==s3[j])
  18. dp[0][j]=true;
  19. else break;
  20. }
  21. for(int i=1;i<=n;i++)
  22. {
  23. if(s1[i]==s3[i])
  24. dp[i][0]=true;
  25. else break;
  26. }
  27. //状态转移方程
  28. for(int i=1;i<=n;i++)
  29. {
  30. for(int j=1;j<=m;j++)
  31. {
  32. //两种方法都可
  33. /*if(s1[i]==s3[i+j]&&dp[i-1][j])
  34. {
  35. dp[i][j]=true;
  36. }
  37. else if(s2[j]==s3[i+j]&&dp[i][j-1])
  38. {
  39. dp[i][j]=true;
  40. }*/
  41. dp[i][j]=((dp[i-1][j]&&s1[i]==s3[i+j])||
  42. (dp[i][j-1]&&s2[j]==s3[i+j]));
  43. }
  44. }
  45. return dp[n][m];
  46. }
  47. };

2.两个字符串的最小ASCII删除和 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给定两个字符串s1 和 s2,返回 使两个字符串相等所需删除字符的 ASCII 值的最小和 

示例 1:

输入: s1 = "sea", s2 = "eat"
输出: 231
解释: 在 "sea" 中删除 "s" 并将 "s" 的值(115)加入总和。
在 "eat" 中删除 "t" 并将 116 加入总和。
结束时,两个字符串相等,115 + 116 = 231 就是符合条件的最小和。

示例 2:

输入: s1 = "delete", s2 = "leet"
输出: 403
解释: 在 "delete" 中删除 "dee" 字符串变成 "let",
将 100[d]+101[e]+101[e] 加入总和。在 "leet" 中删除 "e" 将 101[e] 加入总和。
结束时,两个字符串都等于 "let",结果即为 100+101+101+101 = 403 。
如果改为将两个字符串转换为 "lee" 或 "eet",我们会得到 433 或 417 的结果,比答案更大。

分析:

  1. class Solution {
  2. public:
  3. int minimumDeleteSum(string s1, string s2)
  4. {
  5. int n=s1.size(),m=s2.size();
  6. vector<vector<int>> dp(n+1,vector<int>(m+1));
  7. for(int i=1;i<=n;i++)
  8. {
  9. for(int j=1;j<=m;j++)
  10. {
  11. dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
  12. if(s1[i-1]==s2[j-1])
  13. {
  14. dp[i][j]=max(dp[i][j],dp[i-1][j-1]+s1[i-1]);
  15. }
  16. }
  17. }
  18. int sum1=0;
  19. int sum2=0;
  20. for(auto sh1:s1) sum1+=sh1;
  21. for(auto sh2:s2) sum2+=sh2;
  22. return sum1+sum2-dp[n][m]*2;
  23. }
  24. };

3.最长重复子数组  力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 

示例 1:

输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。

示例 2:

输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
输出:5
  1. class Solution {
  2. public:
  3. int findLength(vector<int>& nums1, vector<int>& nums2)
  4. {
  5. int n=nums1.size();
  6. int m=nums2.size();
  7. vector<vector<int>> dp(n+1,vector<int>(m+1));
  8. int ret=0;
  9. for(int i=1;i<=n;i++)
  10. {
  11. for(int j=1;j<=m;j++)
  12. {
  13. if(nums1[i-1]==nums2[j-1])
  14. {
  15. dp[i][j]=dp[i-1][j-1]+1;
  16. }
  17. else
  18. {
  19. dp[i][j]=0;
  20. }
  21. ret=max(ret,dp[i][j]);
  22. }
  23. }
  24. return ret;
  25. }
  26. };

4.正则表达式匹配  力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

 

示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

示例 3:

输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
  1. lass Solution {
  2. public:
  3. bool isMatch(string s, string p)
  4. {
  5. int n=s.size();
  6. int m=p.size();
  7. vector<vector<bool>> dp(n+1,vector<bool>(m+1));
  8. s=" "+s;
  9. p=" "+p;
  10. dp[0][0]=true;
  11. //初始化
  12. for(int i=2;i<=m;i+=2)
  13. {
  14. if(p[i]=='*')
  15. dp[0][i]=true;
  16. else break;
  17. }
  18. for(int i=1;i<=n;i++)
  19. {
  20. //状态转移方程
  21. for(int j=1;j<=m;j++)
  22. {
  23. if(s[i]==p[j]&&dp[i-1][j-1])
  24. dp[i][j]=true;
  25. else if(p[j]=='.'&&dp[i-1][j-1])
  26. dp[i][j]=true;
  27. else if(p[j]=='*')
  28. {
  29. dp[i][j]=dp[i][j-2] || (p[j-1]=='.'||s[i]==p[j-1]) && dp[i-1][j];
  30. }
  31. }
  32. }
  33. return dp[n][m];//返回值
  34. }
  35. };

5.通配符匹配  力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?''*' 匹配规则的通配符匹配:

  • '?' 可以匹配任何单个字符。
  • '*' 可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。

 

示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "*"
输出:true
解释:'*' 可以匹配任意字符串。

示例 3:

输入:s = "cb", p = "?a"
输出:false
解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
  1. class Solution {
  2. public:
  3. bool isMatch(string s, string p)
  4. {
  5. int n=s.size();
  6. int m=p.size();
  7. vector<vector<bool>> dp(n+1,vector<bool>(m+1));
  8. dp[0][0]=true;
  9. for(int i=1;i<=m;i++)
  10. {
  11. if(p[i-1]=='*')
  12. dp[0][i]=true;
  13. else break;
  14. }
  15. for(int i=1;i<=n;i++)
  16. {
  17. for(int j=1;j<=m;j++)
  18. {
  19. if(p[j-1]=='*')
  20. {
  21. dp[i][j]=dp[i-1][j]||dp[i][j-1];
  22. }
  23. else
  24. {
  25. if(s[i-1]==p[j-1]&&dp[i-1][j-1])
  26. dp[i][j]=true;
  27. else if(p[j-1]=='?'&&dp[i-1][j-1])
  28. dp[i][j]=true;
  29. }
  30. }
  31. }
  32. return dp[n][m];
  33. }
  34. };

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号