• 115. Distinct Subsequences


    问题:

    给定字符串s,匹配串t

    求s中匹配t的方法有多少种。

    匹配:s中存在t的序列。

    Example 1:
    Input: s = "rabbbit", t = "rabbit"
    Output: 3
    Explanation:
    As shown below, there are 3 ways you can generate "rabbit" from S.
    rabbbit
    rabbbit
    rabbbit
    
    Example 2:
    Input: s = "babgbag", t = "bag"
    Output: 5
    Explanation:
    As shown below, there are 5 ways you can generate "bag" from S.
    babgbag
    babgbag
    babgbag
    babgbag
    babgbag
     
    
    Constraints:
    1 <= s.length, t.length <= 1000
    s and t consist of English letters.
    

      

    解法:DP

    1.状态:dp[i][j]:用t[0~j]去匹配s[0~i]所能匹配的方法数。

    i:字符串s[0~i]

    j:字符串t[0~j]

    2.选择:我们将t看作固定的串

    • case_1:s[i]==t[j]:所有匹配包含两部分:SUM {
      • s[i]在匹配串里(t[j]匹配s[i]):dp[i-1][j-1] (方法数=t[0~j-1]匹配s[0~i-1]的情况个数)
      • s[i]不在匹配串里(t[j]匹配s[i]以前的字符):dp[i-1][j](方法数=t[0~j]匹配s[0~i-1]的情况个数) }
    • case_2:s[i]!=t[j]
      • s[i]不在匹配串里(t[j]匹配s[i]以前的字符):dp[i-1][j](方法数=t[0~j]匹配s[0~i-1]的情况个数)

    3.base:

    dp[0][j]:s="", t="XXXXX", 那么所有匹配方法数=0

    dp[i][0]:s="XXXXX",t="",那么所有匹配方法数=1

    4,♻️ 优化

    • dp[i][j]= dp[i-1][j-1] + dp[i-1][j]
    • dp[i][j]= dp[i-1][j]

    当前格子,只与它⬆️ 上方和↖️左上方的格子相关。

    去掉 i,每次保存上一行的内容,

    从后向前 j=m->0,遍历,(可以防止要用的↖️左上方格子先被覆盖更新)

    代码参考:

     1 class Solution {
     2 public:
     3     //dp[i][j]:s[0~i] t[0~j]:the number of ways of construction.
     4     //opt:(let t fixed)
     5     //s[i]==t[j]: dp[i-1][j-1] + dp[i-1][j]
     6     //    2 parts:  t[0~j-1] match s[0~i-1]: then both s&t process one step.
     7                     //(s[i] is included in subsequence)
     8     //              t[0~j] match s[0~i-1]: before s[i], already matched by fixed t
     9                     //(s[i] is excluded in subsequence)
    10     //s[i]!=t[j]: dp[i-1][j]: before s[i], already matched by fixed t
    11                     //(s[i] is excluded in subsequence)
    12     //base:
    13     //dp[0][j]:0
    14     //dp[i][0]:1
    15     int numDistinct(string s, string t) {
    16         int n=s.length(), m=t.length();
    17         vector<vector<long>>dp(n+1, vector<long>(m+1, 0));
    18         for(int i=0; i<=n; i++) dp[i][0]=1;
    19         for(int i=1; i<=n; i++) {
    20             for(int j=1; j<=m; j++) {
    21                 if(s[i-1]==t[j-1]) {
    22                     dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
    23                 } else {
    24                     dp[i][j]=dp[i-1][j];
    25                 }
    26             }
    27         }
    28         return dp[n][m];
    29     }
    30 };

    ♻️ 优化后:

     1 class Solution {
     2 public:
     3     //dp[i][j]:s[0~i] t[0~j]:the number of ways of construction.
     4     //opt:(let t fixed)
     5     //s[i]==t[j]: dp[i-1][j-1] + dp[i-1][j]
     6     //    2 parts:  t[0~j-1] match s[0~i-1]: then both s&t process one step.
     7                     //(s[i] is included in subsequence)
     8     //              t[0~j] match s[0~i-1]: before s[i], already matched by fixed t
     9                     //(s[i] is excluded in subsequence)
    10     //s[i]!=t[j]: dp[i-1][j]: before s[i], already matched by fixed t
    11                     //(s[i] is excluded in subsequence)
    12     //base:
    13     //dp[0][j]:0
    14     //dp[i][0]:1
    15     int numDistinct(string s, string t) {
    16         int n=s.length(), m=t.length();
    17         //vector<vector<long>>dp(n+1, vector<long>(m+1, 0));
    18         vector<long>dp(m+1,0);
    19         dp[0]=1;
    20         //for(int i=0; i<=n; i++) dp[i][0]=1;
    21         for(int i=1; i<=n; i++) {
    22             for(int j=m; j>=1; j--) {
    23                 if(s[i-1]==t[j-1]) {
    24                     //dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
    25                     dp[j]=dp[j-1]+dp[j];
    26                 } else {
    27                     //dp[i][j]=dp[i-1][j];
    28                     dp[j]=dp[j];
    29                 }
    30             }
    31         }
    32         //return dp[n][m];
    33         return dp[m];
    34     }
    35 };
  • 相关阅读:
    XSS挑战之旅平台通关练习
    Vulnhub:view2akill 靶机练习
    Vulnhub:Five86-2-靶机练习
    Vulnhub:Sumo靶机练习
    vulnhub_DMV:1 靶机练习
    vulnhub:Geisha:1 靶机练习
    VulnHub之Aiweb1练习过程
    Linux学习笔记之二
    Linux sudo(CVE-2019-14287)漏洞复现过程
    DoraBox漏洞测试环境搭建和测试过程
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/14605925.html
Copyright © 2020-2023  润新知