LintCode刷题笔记-- Distinct Subsequences
标签:动态规划
题目描述:
Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie,"ACE"
is a subsequence of "ABCDE"
while "AEC"
is not).
解题思路:
昨天想了很久都没有想明白这一问题,昨天在分析这一问题的时候主要是把需要在二维解决的问题放在了一维上解决了。
如果强行进行降维的话,会导致需要在两个循环中维护一个数组。
所以这一题与先前的最长公共子序列非常类似:在两个向量上分解字符串,dp[i][j]所代表的含义为在S的子串(0,i)与T的子串(0,j)的情况下,两者拥有之间拥有的子序列的数量,对于如果两者遍历到i与j所在的位置的字符相等,则在i-1与j-1的位置上的结果加上1。
S与T两者的子串都不存在这一相同字符的状态即dp[i-1][j-1]下的结果便是先前状态,因为在当前状态下,两者的字符串相同,所以只要在先前状态加上1为当前子序列状态的。
所以有关字符串匹配的动态规划,千万要小心的就是两点,一点是初始化的状态,另外一点是转移时的限制条件和相关的子状态。
发现所有问题很多都是背包问题的变种。
参考代码:
public int numDistinct(String S, String T) { // write your code here int[][] dp = new int[S.length()+1][T.length()+1]; dp[0][0] = 1; for(int i = 1; i<=S.length(); i++){ dp[i][0] = 1; } for(int j = 1; j <=T.length(); j++){ dp[0][j] = 0; } for(int i = 1; i<=S.length(); i++){ for(int j=1; j<=T.length(); j++){ dp[i][j] = dp[i-1][j]; if(S.charAt(i-1)==T.charAt(j-1)){ dp[i][j] += dp[i-1][j-1]; } } } return dp[S.length()][T.length()]; } }