给定两个字符串S和Q。任务是计算S和T中的公共子序列数。
例子:
Input : S = “ajblqcpdz”, T = “aefcnbtdi”
Output : 11
Common subsequences are : { “a”, “b”, “c”, “d”, “ab”, “bd”, “ad”, “ac”, “cd”, “abd”, “acd” }
Input : S = “a”, T = “ab”
Output : 1
为了找到两个字符串(例如S和T)中的公共子序列数,我们通过定义2D数组dp [] []使用动态编程,其中dp [i] [j]是字符串S []中的公共子序列数。 0…i-1]和T [0….j-1]。
现在,我们可以将dp [i] [j]定义为
= S [i-1]等于T [j-1]时dp [i] [j-1] + dp [i-1] [j] + 1
这是因为,当S [i-1] == S [j-1]时,使用上述事实,所有先前的公共子序列会在附加一个字符加倍。 dp [i] [j-1]和dp [i-1] [j]都包含dp [i-1] [j-1],因此在我们的递归中将其相加两次,以使计数增加一倍。以前所有常见的子序列。循环中再加上1表示最新的字符匹配:由s1 [i-1]和s2 [j-1]组成的公共子序列
= S [i-1]不等于T [j-1]时dp [i-1] [j] + dp [i] [j-1] – dp [i-1] [j-1]
在这里,我们减去dp [i-1] [j-1]一次,因为它同时存在于dp [i] [j – 1]和dp [i – 1] [j]中,并且相加了两次。
以下是此方法的实现:
C++
// C++ program to count common subsequence in two strings
#include
using namespace std;
// return the number of common subsequence in
// two strings
int CommomSubsequencesCount(string s, string t)
{
int n1 = s.length();
int n2 = t.length();
int dp[n1+1][n2+1];
for (int i = 0; i <= n1; i++) {
for (int j = 0; j <= n2; j++) {
dp[i][j] = 0;
}
}
// for each character of S
for (int i = 1; i <= n1; i++) {
// for each character in T
for (int j = 1; j <= n2; j++) {
// if character are same in both
// the string
if (s[i - 1] == t[j - 1])
dp[i][j] = 1 + dp[i][j - 1] + dp[i - 1][j];
else
dp[i][j] = dp[i][j - 1] + dp[i - 1][j] -
dp[i - 1][j - 1];
}
}
return dp[n1][n2];
}
// Driver Program
int main()
{
string s = "ajblqcpdz";
string t = "aefcnbtdi";
cout << CommomSubsequencesCount(s, t) << endl;
return 0;
}
Java
// Java program to count common subsequence in two strings
public class GFG {
// return the number of common subsequence in
// two strings
static int CommomSubsequencesCount(String s, String t)
{
int n1 = s.length();
int n2 = t.length();
int dp[][] = new int [n1+1][n2+1];
char ch1,ch2 ;
for (int i = 0; i <= n1; i++) {
for (int j = 0; j <= n2; j++) {
dp[i][j] = 0;
}
}
// for each character of S
for (int i = 1; i <= n1; i++) {
// for each character in T
for (int j = 1; j <= n2; j++) {
ch1 = s.charAt(i - 1);
ch2 = t.charAt(j - 1);
// if character are same in both
// the string
if (ch1 == ch2)
dp[i][j] = 1 + dp[i][j - 1] + dp[i - 1][j];
else
dp[i][j] = dp[i][j - 1] + dp[i - 1][j] -
dp[i - 1][j - 1];
}
}
return dp[n1][n2];
}
// Driver code
public static void main (String args[]){
String s = "ajblqcpdz";
String t = "aefcnbtdi";
System.out.println(CommomSubsequencesCount(s, t));
}
// This code is contributed by ANKITRAI1
}
Python3
# Python3 program to count common
# subsequence in two strings
# return the number of common subsequence
# in two strings
def CommomSubsequencesCount(s, t):
n1 = len(s)
n2 = len(t)
dp = [[0 for i in range(n2 + 1)]
for i in range(n1 + 1)]
# for each character of S
for i in range(1, n1 + 1):
# for each character in T
for j in range(1, n2 + 1):
# if character are same in both
# the string
if (s[i - 1] == t[j - 1]):
dp[i][j] = (1 + dp[i][j - 1] +
dp[i - 1][j])
else:
dp[i][j] = (dp[i][j - 1] + dp[i - 1][j] -
dp[i - 1][j - 1])
return dp[n1][n2]
# Driver Code
s = "ajblqcpdz"
t = "aefcnbtdi"
print(CommomSubsequencesCount(s, t))
# This code is contributed by Mohit Kumar
C#
// C# program to count common
// subsequence in two strings
using System;
class GFG
{
// return the number of common
// subsequence in two strings
static int CommomSubsequencesCount(string s,
string t)
{
int n1 = s.Length;
int n2 = t.Length;
int[,] dp = new int [n1 + 1, n2 + 1];
for (int i = 0; i <= n1; i++)
{
for (int j = 0; j <= n2; j++)
{
dp[i, j] = 0;
}
}
// for each character of S
for (int i = 1; i <= n1; i++)
{
// for each character in T
for (int j = 1; j <= n2; j++)
{
// if character are same in
// both the string
if (s[i - 1] == t[j - 1])
dp[i, j] = 1 + dp[i, j - 1] +
dp[i - 1, j];
else
dp[i, j] = dp[i, j - 1] +
dp[i - 1, j] -
dp[i - 1, j - 1];
}
}
return dp[n1, n2];
}
// Driver code
public static void Main ()
{
string s = "ajblqcpdz";
string t = "aefcnbtdi";
Console.Write(CommomSubsequencesCount(s, t));
}
}
// This code is contributed
// by ChitraNayal
PHP
11
时间复杂度: O(n1 * n2)
辅助空间: O(n1 * n2)
资料来源: StackOverflow