【leetcode刷题笔记】:392. 判断子序列

动态规划简单题

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
【leetcode刷题笔记】:392. 判断子序列_第1张图片
思路一:双指针

  • 从t字符串中挨个找s的字符,找到当前字符就在当前位置的下一个位置继续找下一个字符。时间复杂度为O(n+m);(n和m为两个字符串的长度)
bool isSubsequence1(string s, string t) {
    int j,i;
    for(i=0,j=0;i<s.length(),j<t.length();j++)
            if(s[i]==t[j]){
                i++;
            }
    if(i == s.length())
        return true;
    return false;
}

思路二:动态规划
思路:

  • 当前的字符是否满足找到的字符的两个条件:
    • s[i] = t[j] —> 最基本的条件
    • 当前字符的前一个字符也应该找到了其对应的字符,也就是说前面的字符串在t中可以找到它的子序列
  • 那上面就是我们分解的子问题

理解:
用二维数组来dp[i][j]来表示当前的字符是否满足,值为bool型,i为t字符串中的位置,j为s字符串的位置。表示当前位置的s在当前位置的t的前面找得到子序列
dp[i][j]为true的条件就是dp[i-1][j-1]为true,且s[i] = t[j]。

我们刚才说了,dp[i][j]表示的是当前位置的前面子字符串表示是否在t中有相应的子序列,如果这个字符的前面满足了子序列的条件,且s[i] = t[j]的时候,那这个字符也满足当前字符串是子序列的条件,就为true。那么他在接着遍历的时候,即dp[i][j+1]也应该为true
所以dp[i][j-1]为true的时候,dp[i][j]也应该为true。

状态:

  • dp[i][j]为s的从头开始到i的子字符串是否为t从头开始到j的子字符串的子序列

状态转移:

  • dp[i][j] = (dp[i - 1][j - 1] && s[i-1] == s[j-1]) || (dp[i][j - 1])
    • 当前结点为true的条件是,上一个的结点为true,即在[i-1][j-1]之前能找到,或者该结点已经在前面匹配到了即s的该节点在前面已经为true了。(可以理解为,只要该结点找到了,j后面的值都为true)),其中,dp从1开始循环查找
  • dp[i][0] = false 初始化,每个s字符从开头开始匹配,初始化为false
  • dp[0][j] = true 空字符串一定是t的子字符串的子序列,所以dp[0][j]=true
  • 返回dp[sLen][tLen]
bool isSubsequence(string s, string t) {
        int ns = s.length(),nt = t.length();
        vector<vector<bool>> dp(ns+1,vector<bool>(nt+1));//初始化为false;
        int i,j;
        /*
         * 动态规划
         * dp[i][j] = (dp[i - 1][j - 1] && s[i-1] == s[j-1]) || (dp[i][j - 1])
         * 当前结点为true的条件是,上一个的结点为true,即在[i-1][j-1]之前能找到,或者该结点已经在前面匹配到了,
         * 即s的该节点在前面已经为true了。(可以理解为,只要该结点找到了,j后面的值都为true)),其中,dp从1开始循环查找
         * dp[i][0] = false 初始化,每个s字符从开头开始匹配,初始化为false
         * dp[0][j] = true  空字符串一定是t的子字符串的子序列,所以dp[0][j]=true
         */
        dp[0][0] = true;
        for(i = 1;i <= ns; i++)
            dp[i][0] = false;
        for(j = 1;j <= nt; j++)
            dp[0][j] = true;
        for(i=1;i<=ns;i++){
            for(j=1;j<=nt;j++){
                if((dp[i-1][j-1] && (s[i-1] == t[j-1]))  || dp[i][j-1])
                    dp[i][j] = true;
                else
                    dp[i][j] = false;
            }
        }
        return dp[ns][nt];
    }

你可能感兴趣的:(leetcode刷题笔记,leetcode,dp)