• leetcode 字符串动态规划总结


    问题1:leetcode 正则表达式匹配

    请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配

    思路:

    如果 pattern[j] == str[i] || pattern[j] == '.', 此时dp[i][j] = dp[i-1][j-1];

    如果 pattern[j] == '*'
        分两种情况:
        1: 如果pattern[j-1] != str[i] && pattern[j-1] != '.', 此时dp[i][j] = dp[i][j-2] //a*匹配0次
        2: 如果pattern[j-1] == str[i] || pattern[j-1] == '.'
            此时dp[i][j] = dp[i][j-2] // a*匹配0次
            或者 dp[i][j] = dp[i][j-1] // a*匹配1次
            或者 dp[i][j] = dp[i-1][j] // a*匹配多次
     public boolean match(char[] str, char[] pattern)
        {
             if(str == null || pattern == null)  return true;boolean [][] dp = new boolean[str.length+1][pattern.length+1];
            dp[0][0] = true;
            for(int i=1; i<dp[0].length;i++){
                 if(pattern[i-1] == '*'){
                     dp[0][i] = dp[0][i-2];
                 }
            }
            for(int i=1; i<dp.length; i++){
                for(int j=1;j<dp[0].length; j++){
                    if(pattern[j-1] == '*'){
                        if(str[i-1] == pattern[j-2] || pattern[j-2] == '.'){
                            dp[i][j] = dp[i][j-2] || dp[i-1][j] || dp[i][j-1];
                            // 0  多次  一次
                        }
                        else{
                            dp[i][j] = dp[i][j-2];
                        }
                    }
                    else if(str[i-1] == pattern[j-1] || pattern[j-1] == '.'){
                            dp[i][j] = dp[i-1][j-1];
                    }
                }
            }
    
            for(int i=0; i<dp.length; i++){
                for(int j=0; j<dp[0].length; j++){
                    System.out.print(dp[i][j] + " ");
                }
                System.out.println();
            }
            return dp[dp.length-1][dp[0].length-1];
        }

     问题2:  leetcode 44 通配符匹配

    给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。

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

    两个字符串完全匹配才算匹配成功。

    思路: 定义dp[i][j]为s的前i个字符与p的前j个字符是否匹配,那么当p[j] 为‘*’的时候, dp[i][j] = dp[i][j-1] || (i >0 && (dp[i-1][j] || dp[i-1][j-1]) );// 匹配多次或者一次

                当p[j-1]为“?”时候,dp[i][j] = dp[i-1][j-1]

               

    class Solution {
           public boolean isMatch(String s, String p) {
             int m = s.length(), n=p.length();
             boolean[][] dp = new boolean[m+1][n+1];
             dp[0][0] =  true;
    //        String str = "adceb";
    //        String pattern = "*a*b";
             for(int i = 0; i<=m; i++){
                 for(int j=1;j<=n;j++){
                    if( p.charAt(j-1)=='*'){
                          dp[i][j] = dp[i][j-1] || (i >0 && (dp[i-1][j] || dp[i-1][j-1]) );// 匹配多次或者一次
                    }
                    if( i>=1 && (p.charAt(j-1)=='?' || s.charAt(i-1) == p.charAt(j-1)) ){
                          dp[i][j] = dp[i-1][j-1];
                    }
                 }
             }
    
            // for(int i = 0; i<=m; i++){
            //     for(int j=0;j<=n;j++) {
            //       System.out.print(dp[i][j] + " ");
            //     }
            //     System.out.println();
            // }
             return dp[m][n];
        }
    }

    问题三:leetcode 97 交替字符串

    给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

    示例 1:

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

    示例 2:

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

    思路: 定义dp[i][j]为s1的前i个字符与s2的前j个字符是否可以组成s3的前i+j个字符,注意空字符串,所以s1与s2都是从1开始计数的
    class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
              if(s1.equals("")){
                  return s2.equals(s3);
              }
              if(s2.equals("")){
                  return s1.equals(s3);
              }
    
              int m = s1.length(), n = s2.length();
             if(m+n != s3.length()){
                  return false;
              }
              boolean[][] dp = new boolean[m+1][n+1];
              dp[0][0] = true;
    
    //        String s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac";
    
              for(int i=0; i<= m; i++){
                  for(int j=0; j<=n;j++){
                      if(i==0 && j==0) continue;
                      dp[i][j] = (i>0 && s1.charAt(i-1)==s3.charAt(i+j-1) && dp[i-1][j]) ||
                                 (j>0 && s2.charAt(j-1) == s3.charAt(i+j-1) && dp[i][j-1] );
                  }
              }
    
            // for(int i=0; i<= m; i++){
            //     for(int j=0; j<=n;j++) {
            //        System.out.print(dp[i][j] +" ");
            //     }
            //     System.out.println();
            // }
            return dp[m][n];
        }
    }

    leetcode 不同子序列 115

    给定一个字符串 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。

    一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

    示例 1:

    输入: S = "rabbbit", T = "rabbit"
    输出: 3
    解释:
    
    如下图所示, 有 3 种可以从 S 中得到 "rabbit" 的方案。
    (上箭头符号 ^ 表示选取的字母)
    
    rabbbit
    ^^^^ ^^
    rabbbit
    ^^ ^^^^
    rabbbit
    ^^^ ^^^
    

    示例 2:

    输入: S = "babgbag", T = "bag"
    输出: 5
    解释:
    
    如下图所示, 有 5 种可以从 S 中得到 "bag" 的方案。 
    (上箭头符号 ^ 表示选取的字母)
    
    babgbag
    ^^ ^
    babgbag
    ^^    ^
    babgbag
    ^    ^^
    babgbag
      ^  ^^
    babgbag

     思路1: 定义 dp[i][j] 为s[i]等于t[j]的子序列数目:dp[i][j] += dp[k][j-1]; s[k] = t[j-1];

    class Solution {
       public int numDistinct(String s, String t) {
            // S = "rabbbit", T = "rabbit"
    
    //        String S = "babgbag", T = "bag";
            int m = s.length(), n = t.length();
            int[][] dp = new int[m][n];
            // dp[i][j] =  dp[k][j-1]  s[k] == t[j]
            for(int i=0; i<m;i++){
                dp[i][0] = s.charAt(i) == t.charAt(0) ? 1 : 0;
            }
            for(int i=0; i<m;i++){
                for(int j=0; j<n;j++){
                    if(s.charAt(i) == t.charAt(j)) {
                        for (int k = 0; k < i; k++) {
                            if (j>0 && s.charAt(k) == t.charAt(j-1)) {
                                dp[i][j] += dp[k][j-1];
                            }
                        }
                    }
                }
            }
            // for(int i=0; i<m;i++) {
            //     for (int j = 0; j < n; j++) {
            //       System.out.print(dp[i][j]+" ");
            //     }
            //     System.out.println();
            // }
            int result = 0;
            for(int i=0 ; i<m;i++){
                 result += dp[i][n-1];
            }
            return result;
        }
    }

    思路2:

    而是判断S有多少种方式可以得到T。但其实还是动态规划,我们一个定义二维数组dp,dp[i][j]为字符串s(0,i)变换到t(0,j)的变换方法的个数。

    如果S[i]==T[j],那么dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。意思是:如果当前S[i]==T[j],那么当前这个字符即可以保留也可以抛弃,所以变换方法等于保留这个字符的变换方法加上不用这个字符的变换方法, dp[i-1][j-1]为保留这个字符时的变换方法个数,dp[i-1][j]表示抛弃这个字符时的变换方法个数。
    如果S[i]!=T[i],那么dp[i][j] = dp[i-1][j],意思是如果当前字符不等,那么就只能抛弃当前这个字符。

    class Solution {
        public int numDistinct(String s, String t) {
            int[][] res = new int[s.length()+1][t.length()+1];
            res[0][0] = 1;
            for(int i=1;i<t.length()+1;i++)
                res[0][i] = 0;
            for(int i=1;i<s.length()+1;i++)
                res[i][0] = 1;
            for(int i=1;i<s.length()+1;i++)
                for(int j=1;j<t.length()+1;j++){
                    if(s.charAt(i-1)==t.charAt(j-1)){
                        res[i][j] = res[i-1][j-1] + res[i-1][j];
                    }
                    else{
                        res[i][j] = res[i-1][j];
                    }
                }
            return res[s.length()][t.length()];
        }
    }
  • 相关阅读:
    md基本语法
    CodeBlocks安装使用、汉化以及更改配色
    hexo+github搭建个人博客教程和各种坑记录
    GB/T 38637.1-2020 物联网 感知控制设备接入 第1部分:总体要求
    山东大学909数据结构与程序设计考研经验分享
    GB/T 39083-2020 快递服务支付信息交换规范
    GB/T 38829-2020 IPTV媒体交付系统技术要求 内容接入
    GB/T 37733.3-2020 传感器网络 个人健康状态远程监测 第3部分:终端技术要求
    GB/T 38801-2020 内容分发网络技术要求 互联应用场景
    GB/T 30269.809-2020 信息技术 传感器网络 第809部分:测试:基于IP的无线传感器网络网络层协议一致性测试
  • 原文地址:https://www.cnblogs.com/xianbin7/p/10650592.html
Copyright © 2020-2023  润新知