leetcode第一刷_Distinct Subsequences

来源:互联网 发布:ubuntu mount ntfs 编辑:程序博客网 时间:2024/05/29 16:37

应该可以想到是个dp,但是转移方程很难理解。

首先要理解题目要的是什么,求s中包含了多少个形式为t的字串。那么中间结果保存的应该是什么呢?有三种选择,第一,p[i]表示s的前i个字符包含了多少个t,那看看规模扩大时,小规模怎么更新到大规模,当s的长度增加1的时候有什么变化呢,p[i]应该是在p[i-1]的基础上加个数的,但t的规模是固定的,做不到更新。比如aaab中包含了一个ab,那么aaabb中包含多少个呢,完全推不出来出来啊亲,pass。第二,p[j]表示s中包含多少个t的前j个字符,看看这个行不行,不行啊亲,怎么想这小规模和大规模之间也没联系啊,s中包含多少个ab跟s中包含多少个a,是没有直接的关系的。只剩下最后一种选择了,p[i][j]表示s的前i个字符中包含多少个t的前j个字符。总算有点子问题的样子了。

好,下面看看p[i][j]跟什么有关系,显然,p[i][j]一定是包含p[i-1][j]的,因为s多考虑了一个字符,个数一定至少是之前的那个量。那么怎么更新呢?看s[i]和t[j]之间的关系,如果他们相等,那么p[i][j]还应该包含p[i-1][j-1],因为同时增加一个字符,仍然保持了t是s的一部分的性质,如果不相等,那么说明我们应该跳过s的这个字符,它没有用处。

关于边界的计算,当t的长度是0时,即它为空,无论s多长,都肯定包含了一个它。

方程我就不列了,上面的分析应该比较说明问题了。dp的代码永远那么简单,哎:

class Solution {public:    int numDistinct(string S, string T) {        int len1 = S.length(),  len2 = T.length();        if(len2>len1)   return 0;        int p[len1+1][len2+1];        memset(p, 0, sizeof(p));        for(int i=0;i<=len1;i++)    p[i][0] = 1;        for(int i=1;i<=len1;i++){            for(int j=1;j<=len2;j++){                p[i][j] = p[i-1][j]+(S[i-1] == T[j-1]?p[i-1][j-1]:0);            }        }        return p[len1][len2];    }};


0 0
原创粉丝点击