给定两个字符串A和B 。任务是计算在字符串A 中插入字符的方法的数量,以将字符串A 和字符串B 之间的最长公共子序列的长度增加 1。
例子:
Input : A = “aa”, B = “baaa”
Output : 4
The longest common subsequence shared by string A and string B is “aa”, which has a length of 2.
There are two ways that the length of the longest common subsequence can be increased to 3 by adding a single character to string A:
- There are 3 different positions in string A where we could insert an additional ‘a’ to create longest common subsequence “aaa” (i.e at the beginning, middle, and end of the string).
- We can insert a ‘b’ at the beginning of the string for a new longest common subsequence of “baaa”. So, we have 3 + 1 = 4 ways to insert an alphanumeric character into string A and increase the length of the longest common subsequence by one.
假设对于给定的字符串A 和字符串B,它们的 LCS 的长度是k 。让我们在字符串A 中的第 i 个字符后插入一个字符’c’ 并将插入后形成的字符串表示为字符串A new ,如下所示:
A new = A 1, i 。 C 。 A i + 1, n
其中 A i, j表示字符串A 从第 i 个到第 j 个字符和 ‘.’ 的子串。表示两个字符串的串联。
让我们定义 k new为 A new和 B 的 LCS 的长度。 现在我们想知道是否 k new = k + 1。
关键的观察是新插入的字符“c”必须是长度 > k 的 A new和 B 的任何公共子序列的一部分。我们知道这一点是因为如果 A new和 B 有任何公共子序列,这是一个矛盾,因为这意味着 A 和 B 的 LCS 的长度 > k。
使用上述观察,我们可以尝试以下方法。对于每个可能的字符’c’(有 52 个大小写英文字母和 10 个阿拉伯数字,因此有 62 个可能的字符可以插入)以及对于字符串 A 中每个可能的插入 i(有 |a| + 1 个插入位置),让我们尝试在字符串A 中的第 i 个字符之后插入 ‘c’ 并将其与字符串B 中每次出现的 ‘c’ 进行匹配,我们可以尝试匹配这些 ‘c’字符,例如:
A 1,我。 C 。 A i+1, n
B 1, j-1 。 C 。乙j+1, 米
现在,为了检查这样的插入是否产生长度为 k + 1 的 LCS,检查 A 1, i和 B 1, j-1的 LCS 的长度是否加上 LCS A i+的长度就足够了1、n和B j+1,m等于k。在这种情况下,A new和 B 的 lCS 是 k + 1,因为在固定出现的字符’c’ 之间存在匹配,并且它们之间不再有公共子序列。
如果我们可以快速得到 A 和 B 的每两个前缀之间以及它们的每两个后缀之间的 LCS 长度,我们就可以计算出结果。前缀之间的 LCS 长度可以从用于计算字符串A 和字符串B 的 LCS 的动态规划表中读取。在这种方法中,dp[i][j] 存储 A 的最长公共子序列的长度,i和 B i, j 。类似地,可以从类似的 dp 表中读取它们后缀之间的 LCS 长度,该表可以在计算 A反转和 B反转的 LCS 期间计算,其中 S反转表示反转字符串S。
C++
// CPP Program to Number of ways to insert a
// character to increase LCS by one
#include
#define MAX 256
using namespace std;
// Return the Number of ways to insert a
// character to increase the Longest
// Common Subsequence by one
int numberofways(string A, string B, int N, int M)
{
vector pos[MAX];
// Insert all positions of all characters
// in string B.
for (int i = 0; i < M; i++)
pos[B[i]].push_back(i + 1);
// Longest Common Subsequence
int dpl[N + 2][M + 2];
memset(dpl, 0, sizeof(dpl));
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
if (A[i - 1] == B[j - 1])
dpl[i][j] = dpl[i - 1][j - 1] + 1;
else
dpl[i][j] = max(dpl[i - 1][j],
dpl[i][j - 1]);
}
}
int LCS = dpl[N][M];
// Longest Common Subsequence from reverse
int dpr[N + 2][M + 2];
memset(dpr, 0, sizeof(dpr));
for (int i = N; i >= 1; i--) {
for (int j = M; j >= 1; j--) {
if (A[i - 1] == B[j - 1])
dpr[i][j] = dpr[i + 1][j + 1] + 1;
else
dpr[i][j] = max(dpr[i + 1][j],
dpr[i][j + 1]);
}
}
// inserting character between position
// i and i+1
int ans = 0;
for (int i = 0; i <= N; i++) {
for (int j = 0; j < MAX; j++) {
for (auto x : pos[j]) {
if (dpl[i][x - 1] + dpr[i + 1][x + 1] == LCS) {
ans++;
break;
}
}
}
}
return ans;
}
// Driver Program
int main()
{
string A = "aa", B = "baaa";
int N = A.length(), M = B.length();
cout << numberofways(A, B, N, M) << endl;
return 0;
}
Java
// Java Program for Number of ways to insert a
// character to increase LCS by one
import java.util.*;
class GFG
{
static final int MAX = 256;
// Return the Number of ways to insert a
// character to increase the Longest
// Common Subsequence by one
static int numberofways(String A, String B, int N, int M)
{
Vector[] pos = new Vector[MAX];
// Insert all positions of all characters
// in string B.
for (int i = 0; i < MAX; i++)
pos[i] = new Vector<>();
for (int i = 0; i < M; i++)
pos[B.charAt(i)].add(i + 1);
// Longest Common Subsequence
int[][] dpl = new int[N + 2][M + 2];
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= M; j++)
{
if (A.charAt(i - 1) == B.charAt(j - 1))
dpl[i][j] = dpl[i - 1][j - 1] + 1;
else
dpl[i][j] = Math.max(dpl[i - 1][j],
dpl[i][j - 1]);
}
}
int LCS = dpl[N][M];
// Longest Common Subsequence from reverse
int[][] dpr = new int[N + 2][M + 2];
for (int i = N; i >= 1; i--)
{
for (int j = M; j >= 1; j--)
{
if (A.charAt(i - 1) == B.charAt(j - 1))
dpr[i][j] = dpr[i + 1][j + 1] + 1;
else
dpr[i][j] = Math.max(dpr[i + 1][j],
dpr[i][j + 1]);
}
}
// inserting character between position
// i and i+1
int ans = 0;
for (int i = 0; i <= N; i++)
{
for (int j = 0; j < MAX; j++)
{
for (int x : pos[j])
{
if (dpl[i][x - 1] +
dpr[i + 1][x + 1] == LCS)
{
ans++;
break;
}
}
}
}
return ans;
}
// Driver Code
public static void main(String[] args)
{
String A = "aa", B = "baaa";
int N = A.length(), M = B.length();
System.out.println(numberofways(A, B, N, M));
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python Program to Number of ways to insert a
# character to increase LCS by one
MAX = 256
def numberofways(A, B, N, M):
pos = [[] for _ in range(MAX)]
# Insert all positions of all characters
# in string B
for i in range(M):
pos[ord(B[i])].append(i+1)
# Longest Common Subsequence
dpl = [[0] * (M+2) for _ in range(N+2)]
for i in range(1, N+1):
for j in range(1, M+1):
if A[i - 1] == B[j - 1]:
dpl[i][j] = dpl[i - 1][j - 1] + 1
else:
dpl[i][j] = max(dpl[i - 1][j],
dpl[i][j - 1])
LCS = dpl[N][M]
# Longest Common Subsequence from reverse
dpr = [[0] * (M+2) for _ in range(N+2)]
for i in range(N, 0, -1):
for j in range(M, 0, -1):
if A[i - 1] == B[j - 1]:
dpr[i][j] = dpr[i + 1][j + 1] + 1
else:
dpr[i][j] = max(dpr[i + 1][j],
dpr[i][j + 1])
# inserting character between position
# i and i+1
ans = 0
for i in range(N+1):
for j in range(MAX):
for x in pos[j]:
if dpl[i][x - 1] + dpr[i + 1][x + 1] == LCS:
ans += 1
break
return ans
# Driver Code
if __name__ == "__main__":
A = "aa"
B = "baaa"
N = len(A)
M = len(B)
print(numberofways(A, B, N, M))
# This code is contributed by vibhu4agarwal
C#
// C# Program for Number of ways to insert a
// character to increase LCS by one
using System;
using System.Collections.Generic;
class GFG
{
static readonly int MAX = 256;
// Return the Number of ways to insert a
// character to increase the longest
// Common Subsequence by one
static int numberofways(String A, String B,
int N, int M)
{
List[] pos = new List[MAX];
// Insert all positions of all characters
// in string B.
for (int i = 0; i < MAX; i++)
pos[i] = new List();
for (int i = 0; i < M; i++)
pos[B[i]].Add(i + 1);
// longest Common Subsequence
int[,] dpl = new int[N + 2, M + 2];
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= M; j++)
{
if (A[i - 1] == B[j - 1])
dpl[i, j] = dpl[i - 1, j - 1] + 1;
else
dpl[i, j] = Math.Max(dpl[i - 1, j],
dpl[i, j - 1]);
}
}
int LCS = dpl[N, M];
// longest Common Subsequence from reverse
int[,] dpr = new int[N + 2, M + 2];
for (int i = N; i >= 1; i--)
{
for (int j = M; j >= 1; j--)
{
if (A[i - 1] == B[j - 1])
dpr[i, j] = dpr[i + 1, j + 1] + 1;
else
dpr[i, j] = Math.Max(dpr[i + 1, j],
dpr[i, j + 1]);
}
}
// inserting character between position
// i and i+1
int ans = 0;
for (int i = 0; i <= N; i++)
{
for (int j = 0; j < MAX; j++)
{
foreach (int x in pos[j])
{
if (dpl[i, x - 1] +
dpr[i + 1, x + 1] == LCS)
{
ans++;
break;
}
}
}
}
return ans;
}
// Driver Code
public static void Main(String[] args)
{
String A = "aa", B = "baaa";
int N = A.Length, M = B.Length;
Console.WriteLine(numberofways(A, B, N, M));
}
}
// This code is contributed by 29AjayKumar
Javascript
输出:
4
时间复杂度: O(N x M)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。