给定两个字符串S和T,找到S中T的不同出现次数作为子序列。
例子:
Input: S = banana, T = ban
Output: 3
Explanation: T appears in S as below three subsequences.
[ban], [ba n], [b an]
Input: S = geeksforgeeks, T = ge
Output: 6
Explanation: T appears in S as below three subsequences.
[ge], [ ge], [g e], [g e] [g e]
and [ g e]
方法:创建一个递归函数,使其返回与T匹配的S的子序列数。在这里,m是T的长度,n是S的长度。可以按以下方式递归定义此问题。
- 基本案例:
- 给定字符串T是一个空字符串,返回1作为空字符串可以是所有字符串的子序列。
- 假定字符串S是一个空字符串,则返回0,因为没有字符串可以是空字符串。
- 如果S和T的最后一个字符不匹配,则删除S的最后一个字符并再次调用递归函数。因为S的最后一个字符不能成为子序列的一部分,或将其删除并检查其他字符。
- 如果S的最后一个字符匹配,则可能有两种可能性,第一个可能是子序列,其中S的最后一个字符是它的一部分,其次是它不是子序列的一部分。因此,所需值将是两者之和。调用递归函数一次,删除两个字符串的最后一个字符,然后再次调用,只删除S的最后一个字符。
递归情况:
蓝色圆角矩形表示接受状态或存在子序列,红色圆角矩形表示无法形成子序列。
由于上述递归结果中存在重叠的子问题,因此可以采用动态编程方法来解决上述问题。将子问题存储在Hashmap或数组中,并在再次调用该函数时返回该值。
算法:
- 创建2D数组mat [m + 1] [n + 1] ,其中m是字符串T的长度,n是字符串S的长度。mat [i] [j]表示子字符串S(1。)的不同子序列数。 i)和子字符串T(1..j),因此mat [m] [n]包含我们的解决方案。
- 用全0初始化第一列。空字符串不能包含其他字符串作为后继序列
- 用全1初始化第一行。空字符串是全部的子序列。
- 以自下而上的方式填充矩阵,即,首先计算当前字符串的所有子问题。
- 从头到尾遍历字符串T。 (计数器是我)
- 对于外循环的每次迭代,从头到尾遍历字符串S。 (计数器为j )
- 如果在我字符串T匹配的与第j个字符串S的字符个索引的字符时,获得的值考虑两种情况。首先,是所有不处于S最后一个字符的子串和第二个是没有两个,即,垫最后一个字符的子串[I + 1] [j] +垫[i] [j]。
- 否则,即使删除了S的第j个字符,该值也将相同,即mat [i + 1] [j]
- 打印mat [m-1] [n-1]的值作为答案。
C++
/* C/C++ program to count number of times S appears
as a subsequence in T */
#include
using namespace std;
int findSubsequenceCount(string S, string T)
{
int m = T.length(), n = S.length();
// T can't appear as a subsequence in S
if (m > n)
return 0;
// mat[i][j] stores the count of occurrences of
// T(1..i) in S(1..j).
int mat[m + 1][n + 1];
// Initializing first column with all 0s. An empty
// string can't have another string as suhsequence
for (int i = 1; i <= m; i++)
mat[i][0] = 0;
// Initializing first row with all 1s. An empty
// string is subsequence of all.
for (int j = 0; j <= n; j++)
mat[0][j] = 1;
// Fill mat[][] in bottom up manner
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// If last characters don't match, then value
// is same as the value without last character
// in S.
if (T[i - 1] != S[j - 1])
mat[i][j] = mat[i][j - 1];
// Else value is obtained considering two cases.
// a) All substrings without last character in S
// b) All substrings without last characters in
// both.
else
mat[i][j] = mat[i][j - 1] + mat[i - 1][j - 1];
}
}
/* uncomment this to print matrix mat
for (int i = 1; i <= m; i++, cout << endl)
for (int j = 1; j <= n; j++)
cout << mat[i][j] << " "; */
return mat[m][n];
}
// Driver code to check above method
int main()
{
string T = "ge";
string S = "geeksforgeeks";
cout << findSubsequenceCount(S, T) << endl;
return 0;
}
Java
// Java program to count number of times
// S appears as a subsequence in T
import java.io.*;
class GFG {
static int findSubsequenceCount(String S, String T)
{
int m = T.length();
int n = S.length();
// T can't appear as a subsequence in S
if (m > n)
return 0;
// mat[i][j] stores the count of
// occurrences of T(1..i) in S(1..j).
int mat[][] = new int[m + 1][n + 1];
// Initializing first column with
// all 0s. An emptystring can't have
// another string as suhsequence
for (int i = 1; i <= m; i++)
mat[i][0] = 0;
// Initializing first row with all 1s.
// An empty string is subsequence of all.
for (int j = 0; j <= n; j++)
mat[0][j] = 1;
// Fill mat[][] in bottom up manner
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// If last characters don't match,
// then value is same as the value
// without last character in S.
if (T.charAt(i - 1) != S.charAt(j - 1))
mat[i][j] = mat[i][j - 1];
// Else value is obtained considering two cases.
// a) All substrings without last character in S
// b) All substrings without last characters in
// both.
else
mat[i][j] = mat[i][j - 1] + mat[i - 1][j - 1];
}
}
/* uncomment this to print matrix mat
for (int i = 1; i <= m; i++, cout << endl)
for (int j = 1; j <= n; j++)
System.out.println ( mat[i][j] +" "); */
return mat[m][n];
}
// Driver code to check above method
public static void main(String[] args)
{
String T = "ge";
String S = "geeksforgeeks";
System.out.println(findSubsequenceCount(S, T));
}
}
// This code is contributed by vt_m
Python3
# Python3 program to count number of times
# S appears as a subsequence in T
def findSubsequenceCount(S, T):
m = len(T)
n = len(S)
# T can't appear as a subsequence in S
if m > n:
return 0
# mat[i][j] stores the count of
# occurrences of T(1..i) in S(1..j).
mat = [[0 for _ in range(n + 1)]
for __ in range(m + 1)]
# Initializing first column with all 0s. x
# An empty string can't have another
# string as suhsequence
for i in range(1, m + 1):
mat[i][0] = 0
# Initializing first row with all 1s.
# An empty string is subsequence of all.
for j in range(n + 1):
mat[0][j] = 1
# Fill mat[][] in bottom up manner
for i in range(1, m + 1):
for j in range(1, n + 1):
# If last characters don't match,
# then value is same as the value
# without last character in S.
if T[i - 1] != S[j - 1]:
mat[i][j] = mat[i][j - 1]
# Else value is obtained considering two cases.
# a) All substrings without last character in S
# b) All substrings without last characters in
# both.
else:
mat[i][j] = (mat[i][j - 1] +
mat[i - 1][j - 1])
return mat[m][n]
# Driver Code
if __name__ == "__main__":
T = "ge"
S = "geeksforgeeks"
print(findSubsequenceCount(S, T))
# This code is contributed
# by vibhu4agarwal
C#
// C# program to count number of times
// S appears as a subsequence in T
using System;
class GFG {
static int findSubsequenceCount(string S, string T)
{
int m = T.Length;
int n = S.Length;
// T can't appear as a subsequence in S
if (m > n)
return 0;
// mat[i][j] stores the count of
// occurrences of T(1..i) in S(1..j).
int[, ] mat = new int[m + 1, n + 1];
// Initializing first column with
// all 0s. An emptystring can't have
// another string as suhsequence
for (int i = 1; i <= m; i++)
mat[i, 0] = 0;
// Initializing first row with all 1s.
// An empty string is subsequence of all.
for (int j = 0; j <= n; j++)
mat[0, j] = 1;
// Fill mat[][] in bottom up manner
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// If last characters don't match,
// then value is same as the value
// without last character in S.
if (T[i - 1] != S[j - 1])
mat[i, j] = mat[i, j - 1];
// Else value is obtained considering two cases.
// a) All substrings without last character in S
// b) All substrings without last characters in
// both.
else
mat[i, j] = mat[i, j - 1] + mat[i - 1, j - 1];
}
}
/* uncomment this to print matrix mat
for (int i = 1; i <= m; i++, cout << endl)
for (int j = 1; j <= n; j++)
System.out.println ( mat[i][j] +" "); */
return mat[m, n];
}
// Driver code to check above method
public static void Main()
{
string T = "ge";
string S = "geeksforgeeks";
Console.WriteLine(findSubsequenceCount(S, T));
}
}
// This code is contributed by vt_m
PHP
$n)
return 0;
// mat[i][j] stores the count of
// occurrences of T(1..i) in S(1..j).
$mat = array(array());
// Initializing first column with all 0s.
// An empty string can't have another
// string as suhsequence
for ($i = 1; $i <= $m; $i++)
$mat[$i][0] = 0;
// Initializing first row with all 1s.
// An empty string is subsequence of all.
for ($j = 0; $j <= $n; $j++)
$mat[0][$j] = 1;
// Fill mat[][] in bottom up manner
for ($i = 1; $i <= $m; $i++)
{
for ($j = 1; $j <= $n; $j++)
{
// If last characters don't match,
// then value is same as the value
// without last character in S.
if ($T[$i - 1] != $S[$j - 1])
$mat[$i][$j] = $mat[$i][$j - 1];
// Else value is obtained considering two cases.
// a) All substrings without last character in S
// b) All substrings without last characters in
// both.
else
$mat[$i][$j] = $mat[$i][$j - 1] +
$mat[$i - 1][$j - 1];
}
}
/* uncomment this to print matrix mat
for (int i = 1; i <= m; i++, cout << endl)
for (int j = 1; j <= n; j++)
cout << mat[i][j] << " "; */
return $mat[$m][$n];
}
// Driver Code
$T = "ge";
$S = "geeksforgeeks";
echo findSubsequenceCount($S, $T) . "\n";
// This code is contributed
// by Akanksha Rai
输出:
6
复杂度分析:
- 时间复杂度: O(m * n)。
只需要遍历矩阵一次,因此时间Compelxiy为O(m * n) - 辅助空间: O(m * n)。
需要一个大小为m * n的矩阵,因此空间复杂度为O(m * n)。
注意:由于mat [i] [j]仅访问当前行和前一行的元素,因此仅使用两行将m * n的空间减少到2 * n,就可以优化辅助空间。