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:

C++--两个数组的dp问题(2)_第1张图片

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

示例 2:

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

示例 3:

输入:s1 = "", s2 = "", s3 = ""
输出:true
class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) 
    {
        int n=s1.size();
        int m=s2.size();
       if(m+n!=s3.size())
        return false;
        s1=" "+s1;
        s2=" "+s2;
        s3=" "+s3;
        //初始化
        vector> dp(n+1,vector(m+1));
        dp[0][0]=true;
        for(int j=1;j<=m;j++)
        {
            if(s2[j]==s3[j])
                dp[0][j]=true;
            else break;
        }
        for(int i=1;i<=n;i++)
        {
            if(s1[i]==s3[i])
                dp[i][0]=true;
            else break;
        }
        //状态转移方程
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                //两种方法都可
                /*if(s1[i]==s3[i+j]&&dp[i-1][j])
                {
                    dp[i][j]=true;
                }
                else if(s2[j]==s3[i+j]&&dp[i][j-1])
                {
                    dp[i][j]=true;
                }*/
                dp[i][j]=((dp[i-1][j]&&s1[i]==s3[i+j])||
                            (dp[i][j-1]&&s2[j]==s3[i+j]));
            }
        }
        return dp[n][m];
    }
};

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 的结果,比答案更大。

分析:

class Solution {
public:
    int minimumDeleteSum(string s1, string s2) 
    {
        int n=s1.size(),m=s2.size();
        vector> dp(n+1,vector(m+1));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;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 sum1=0;
        int sum2=0;

        for(auto sh1:s1) sum1+=sh1;
        for(auto sh2:s2) sum2+=sh2;
        return sum1+sum2-dp[n][m]*2;
    }
};

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
class Solution {
public:
    int findLength(vector& nums1, vector& nums2) 
    {
        int n=nums1.size();
        int m=nums2.size();
        vector> dp(n+1,vector(m+1));
        int ret=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(nums1[i-1]==nums2[j-1]) 
                {
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else
                {
                    dp[i][j]=0;
                }
                ret=max(ret,dp[i][j]);
            }
            
        }
        return ret;
    }
};

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
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
lass Solution {
public:
    bool isMatch(string s, string p) 
    {
        int n=s.size();
        int m=p.size();
        vector> dp(n+1,vector(m+1));
        s=" "+s;
        p=" "+p;
        dp[0][0]=true;
        //初始化
        for(int i=2;i<=m;i+=2)
        {
            if(p[i]=='*')
                dp[0][i]=true;
            else break;
        }
        for(int i=1;i<=n;i++)
        {
            //状态转移方程
            for(int j=1;j<=m;j++)
            {
                if(s[i]==p[j]&&dp[i-1][j-1])
                    dp[i][j]=true;
                else if(p[j]=='.'&&dp[i-1][j-1])
                    dp[i][j]=true;
                else if(p[j]=='*')
                {
                    dp[i][j]=dp[i][j-2] || (p[j-1]=='.'||s[i]==p[j-1]) && dp[i-1][j];
                }

            }
        }
        return dp[n][m];//返回值
    }
};

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'。
class Solution {
public:
    bool isMatch(string s, string p) 
    {
        int n=s.size();
        int m=p.size();
        vector> dp(n+1,vector(m+1));
        dp[0][0]=true;
        for(int i=1;i<=m;i++)
        {
            if(p[i-1]=='*')
                dp[0][i]=true;
            else break;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(p[j-1]=='*')
                {
                    dp[i][j]=dp[i-1][j]||dp[i][j-1];
                }
                else
                {
                   if(s[i-1]==p[j-1]&&dp[i-1][j-1])
                        dp[i][j]=true;
                    else if(p[j-1]=='?'&&dp[i-1][j-1])
                        dp[i][j]=true;
                }
            }
        }
        return dp[n][m];
    }
};

你可能感兴趣的:(c++,开发语言)