LeetCode-----第115题-----不同的子序列

不同的子序列

难度:困难

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

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

题目数据保证答案符合 32 位带符号整数范围。

示例 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
    ^^^

题目分析:

       这个题目一看就是DP问题,但是没有列表的习惯,一想觉得难度太大。我们列表如下所示,进行匹配。找出规律。

       1.状态转换方程:f[i][j] = f[i-1][j-1] + f[i][j-1](当字符匹配时,即t[i] == s[j](这里需要注意这里的坐标比f的坐标小1))

       2.选择二维数组作为数据结构

       3.初始化,将f[0][0] = 1, 上面第一行赋值为1,左边第一列赋值为0(除了第一个数)

参考代码:

class Solution {
public:
    int numDistinct(string s, string t) {
        vector<vector<long long> > f(t.size()+1,vector<long long>(s.size()+1,0));

        if(t.empty())
            return 1;
        
        if(s.empty())
            return 0;
        
        //初始化状态转换方程最上面一行和最左边一列
        f[0][0] = 1;
        for(long long i = 1; i < s.size(); i++)
        {
            f[0][i] = 1;
        }
        for(long long i = 1; i < t.size(); i++)
        {
            f[i][0] = 0;
        }

        //填表
        for(long long i = 1; i <= t.size(); i++)
        {
            for(long long j = 1; j <= s.size(); j++)
            {
                if(t[i-1] == s[j-1])//注意这里的坐标
                    f[i][j] = f[i-1][j-1] + f[i][j-1];
                else
                    f[i][j] = f[i][j-1];
            }
        }
        return f[t.size()][s.size()];
    }
};

猜你喜欢

转载自blog.csdn.net/L_smartworld/article/details/107467850