给定一个字符串 s 和一个字符串 t ,s = "rabbbit", t = "rabbit",计算在 s 的子序列中 t 出现的个数。
字符串的一个 子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)
此时我们通过矩阵来解决该问题,矩阵的列为母串,行为子串。创建一个二维数组x,对数组进行初始化,当子串长度为0时,所有次数都是1,当母串长度为0时,所有次数都是0。接着,如果子串的最后一个字母和母串的最后一个字母不同,说明新加的母串字母没有产生新的可能性,可以沿用该子串在较短母串的出现次数,所以x[i][j] = x[i][j-1]。如果子串的最后一个字母和母串的最后一个字母相同,说明新加的母串字母带来了新的可能性,我们不仅算上x[i][j-1],也要算上新的可能性。新的可能性其实就是在既没有最后这个母串字母也没有最后这个子串字母时,子串出现的次数,我们相当于为所有这些可能性都添加一个新的可能。所以,这时x[i][j] = x[i][j-1] + x[i-1][j-1],下图是以rabbbit和rabbit为例的矩阵示意图。计算元素值时,当末尾字母一样,实际上是左方数字加左上方数字,当不一样时,就是左方的数字。
r | a | b | b | b | i | t | |||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |
r | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
a | 2 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
b | 3 | 0 | 0 | 0 | 1 | 2 | 3 | 3 | 3 |
b | 4 | 0 | 0 | 0 | 0 | 1 | 3 | 3 | 3 |
i | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 3 |
t | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 3 |
java实现代码:
class Solution { private static int[][]x=new int[1001][1001]; public int numDistinct(String s, String t) { for(int i=0;i<=s.length();i++) x[0][i]=1;//初始化0行的列 for(int i=1;i<=t.length();i++) x[i][0]=0;//初始化0列的行 for(int i=1;i<=t.length();i++) for(int j=1;j<=s.length();j++) { if(t.charAt(i-1)==s.charAt(j-1)) x[i][j]=x[i-1][j-1]+x[i][j-1]; else x[i][j]=x[i][j-1]; } return x[t.length()][s.length()]; } }