問題描述:java
<pre> 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). Here is an example: S = "rabbbit", T = "rabbit" Return 3. </pre>code
問題反覆讀了幾遍感受才理解。首先想到的是用遞歸的方法試試:orm
public class DistinctSubsequences { private int numDS = 0; public int numDistinct(String S, String T) { numDS = 0; searchSequence(S, T); return numDS; } private void searchSequence(String S, String T) { //System.out.println("searchSequence(" + S + ", " + T + ")"); if (S.length() < T.length()) { return; } if (T.length() == 0) { numDS++; return; } int slen = S.length(); for (int i = 0; i < slen; i++) { if (S.charAt(i) == getHead(T)) { searchSequence(cutHead(S, i+1), cutHead(T, 1)); } } } public String cutHead(String s, int begin) { return s.substring(begin, s.length()); } public char getHead(String s) { return s.charAt(0); } }
提交後報出超時的錯誤。感受上應該能夠用動態規劃來作,由於畢業找工做時,發現不少用遞歸作的題最終解答都是動態規劃,想了好久,發現能夠這樣:遞歸
public class DistinctSubsequences { private int numDS = 0; public int numDistinct(String S, String T) { return dpSearchSequence(S, T); } private int dpSearchSequence(String S, String T) { int slen = S.length(); int tlen = T.length(); if (slen < tlen || slen == 0 || tlen == 0) return 0; int dp[][] = new int[tlen][slen]; for (int i = 0; i < tlen; i++) { for (int j = i; j < slen; j++) { if (T.charAt(i) == S.charAt(j)) { if (i > 0) { dp[i][j] = dp[i-1][j-1] // S[0..j-1] 中 T[0..i-1] 出現的次數 + dp[i][j-1]; // S[0..j-1] 中 T[0..i] 出現的次數 // 例如:計算 abcc 中子序列 abc 次數,能夠這樣遞歸: // recur(abcc, abc) { // return recur(abc, ab) + recur(abc, abc) // } } else { if (j > 0) { dp[i][j] = dp[i][j-1] + 1; } else { dp[i][j] = 1; } } } else { if (j > 0) { dp[i][j] = dp[i][j-1]; } else { dp[i][j] = 0; } } } } return dp[tlen-1][slen-1]; } }
對動態規劃的題仍是很不熟,仍是得多看看啊。rem