📌  相关文章
📜  插入字符以使LCS增加一的方式的数目

📅  最后修改于: 2021-04-29 08:11:17             🧑  作者: Mango

给定两个字符串AB。的任务是计数的方法来插入字符串A的字符被1至增加最长公共子序列的字符串A和字符串B之间的长度的数目。

例子:

假设对于给定的字符串A和字符串B,它们的LCS的长度为k 。让我们在字符串A中的第ith个字符之后插入一个字符’c’,并将插入后形成的字符串表示为字符串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中的第ith个字符后插入“ c”,并将其与字符串B中每次出现的“ c”相匹配,我们可以尝试匹配以下这些“ c”字符:
A 1,我。 C 。 A i + 1,n
B 1,j-1 。 C 。 B j + 1,m

现在,为了检查这样的插入是否产生了长度为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长度,则可以计算出结果。可以从用于计算字符串A和字符串B的LCS的动态编程表中读取LCS前缀之间的长度。在这种方法中,dp [i] [j]存储A ,i和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


输出:

4

时间复杂度: O(N x M)