鉴于较低的字母字符两个字符串,我们需要找到办法的号码中插入第一个字符串中的字符,使得由一个两个字符串增加LCS的长度。
例子:
Input : str1 = “abab”, str2 = “abc”
Output : 3
LCS length of given two strings is 2.
There are 3 ways of insertion in str1,
to increase the LCS length by one which
are enumerated below,
str1 = “abcab” str2 = “abc” LCS length = 3
str1 = “abacb” str2 = “abc” LCS length = 3
str1 = “ababc” str2 = “abc” LCS length = 3
Input : str1 = “abcabc”, str2 = “abcd”
Output : 4
这个想法是尝试在第一个字符串的每个位置上所有26个可能的字符,如果str1的长度是m,那么可以在(m + 1)个位置插入一个新字符,现在假设在任何时候将字符c插入在str1的第i个位置那么我们将其与str2中所有具有字符c的位置进行匹配。假设一个这样的位置是j,那么对于LCS的总长度要比以前大一倍,以下条件应满足,
LCS(str1[1, m], str2[1, n]) = LCS(str1[1, i], str2[1, j-1]) +
LCS(str1[i+1, m], str2[j+1, n])
上式表示,插入字符的后缀和前缀子字符串的LCS的总和必须与字符串的总LCS相同,因此,当在第一个字符串插入相同的字符时,它将使LCS的长度增加一。
在下面的代码中,两个二维数组lcsl和lcsr用于分别存储字符串的前缀和后缀的LCS。可以在此处找到填充这些2D阵列的方法。
请参阅下面的代码以更好地理解,
C++
// C++ program to get number of ways to increase
// LCS by 1
#include
using namespace std;
#define M 26
// Utility method to get integer position of lower
// alphabet character
int toInt(char ch)
{
return (ch - 'a');
}
// Method returns total ways to increase LCS length by 1
int waysToIncreaseLCSBy1(string str1, string str2)
{
int m = str1.length(), n = str2.length();
// Fill positions of each character in vector
vector position[M];
for (int i = 1; i <= n; i++)
position[toInt(str2[i-1])].push_back(i);
int lcsl[m + 2][n + 2];
int lcsr[m + 2][n + 2];
// Initializing 2D array by 0 values
for (int i = 0; i <= m+1; i++)
for (int j = 0; j <= n + 1; j++)
lcsl[i][j] = lcsr[i][j] = 0;
// Filling LCS array for prefix substrings
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (str1[i-1] == str2[j-1])
lcsl[i][j] = 1 + lcsl[i-1][j-1];
else
lcsl[i][j] = max(lcsl[i-1][j],
lcsl[i][j-1]);
}
}
// Filling LCS array for suffix substrings
for (int i = m; i >= 1; i--)
{
for (int j = n; j >= 1; j--)
{
if (str1[i-1] == str2[j-1])
lcsr[i][j] = 1 + lcsr[i+1][j+1];
else
lcsr[i][j] = max(lcsr[i+1][j],
lcsr[i][j+1]);
}
}
// Looping for all possible insertion positions
// in first string
int ways = 0;
for (int i=0; i<=m; i++)
{
// Trying all possible lower case characters
for (char c='a'; c<='z'; c++)
{
// Now for each character, loop over same
// character positions in second string
for (int j=0; j
Java
// Java program to get number of ways to increase
// LCS by 1
import java.util.*;
class GFG
{
static int M = 26;
// Method returns total ways to increase
// LCS length by 1
static int waysToIncreaseLCSBy1(String str1,
String str2)
{
int m = str1.length(), n = str2.length();
// Fill positions of each character in vector
Vector[] position = new Vector[M];
for (int i = 0; i < M; i++)
position[i] = new Vector<>();
for (int i = 1; i <= n; i++)
position[str2.charAt(i - 1) - 'a'].add(i);
int[][] lcsl = new int[m + 2][n + 2];
int[][] lcsr = new int[m + 2][n + 2];
// Initializing 2D array by 0 values
for (int i = 0; i <= m + 1; i++)
for (int j = 0; j <= n + 1; j++)
lcsl[i][j] = lcsr[i][j] = 0;
// Filling LCS array for prefix substrings
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (str1.charAt(i - 1) == str2.charAt(j - 1))
lcsl[i][j] = 1 + lcsl[i - 1][j - 1];
else
lcsl[i][j] = Math.max(lcsl[i - 1][j],
lcsl[i][j - 1]);
}
}
// Filling LCS array for suffix substrings
for (int i = m; i >= 1; i--)
{
for (int j = n; j >= 1; j--)
{
if (str1.charAt(i - 1) == str2.charAt(j - 1))
lcsr[i][j] = 1 + lcsr[i + 1][j + 1];
else
lcsr[i][j] = Math.max(lcsr[i + 1][j],
lcsr[i][j + 1]);
}
}
// Looping for all possible insertion positions
// in first string
int ways = 0;
for (int i = 0; i <= m; i++)
{
// Trying all possible lower case characters
for (char d = 0; d < 26; d++)
{
// Now for each character, loop over same
// character positions in second string
for (int j = 0; j < position[d].size(); j++)
{
int p = position[d].elementAt(j);
// If both, left and right substrings make
// total LCS then increase result by 1
if (lcsl[i][p - 1] +
lcsr[i + 1][p + 1] == lcsl[m][n])
ways++;
}
}
}
return ways;
}
// Driver Code
public static void main(String[] args)
{
String str1 = "abcabc";
String str2 = "abcd";
System.out.println(waysToIncreaseLCSBy1(str1, str2));
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python3 program to get number of ways to increase
# LCS by 1
M = 26
# Method returns total ways to increase LCS length by 1
def waysToIncreaseLCSBy1(str1, str2):
m = len(str1)
n = len(str2)
# Fill positions of each character in vector
# vector position[M];
position = [[] for i in range(M)]
for i in range(1, n+1, 1):
position[ord(str2[i-1])-97].append(i)
# Initializing 2D array by 0 values
lcsl = [[0 for i in range(n+2)] for j in range(m+2)]
lcsr = [[0 for i in range(n+2)] for j in range(m+2)]
# Filling LCS array for prefix substrings
for i in range(1, m+1, 1):
for j in range(1, n+1,1):
if (str1[i-1] == str2[j-1]):
lcsl[i][j] = 1 + lcsl[i-1][j-1]
else:
lcsl[i][j] = max(lcsl[i-1][j],
lcsl[i][j-1])
# Filling LCS array for suffix substrings
for i in range(m, 0, -1):
for j in range(n, 0, -1):
if (str1[i-1] == str2[j-1]):
lcsr[i][j] = 1 + lcsr[i+1][j+1]
else:
lcsr[i][j] = max(lcsr[i+1][j],
lcsr[i][j+1])
# Looping for all possible insertion positions
# in first string
ways = 0
for i in range(0, m+1,1):
# Trying all possible lower case characters
for C in range(0, 26,1):
# Now for each character, loop over same
# character positions in second string
for j in range(0, len(position[C]),1):
p = position[C][j]
# If both, left and right substrings make
# total LCS then increase result by 1
if (lcsl[i][p-1] + lcsr[i+1][p+1] == lcsl[m][n]):
ways += 1
return ways
# Driver code to test above methods
str1 = "abcabc"
str2 = "abcd"
print(waysToIncreaseLCSBy1(str1, str2))
# This code is contributed by ankush_953
C#
// C# program to get number of ways
// to increase LCS by 1
using System;
using System.Collections.Generic;
class GFG{
static int M = 26;
// Method returns total ways to increase
// LCS length by 1
static int waysToIncreaseLCSBy1(String str1,
String str2)
{
int m = str1.Length, n = str2.Length;
// Fill positions of each character in vector
List[] position = new List[M];
for(int i = 0; i < M; i++)
position[i] = new List();
for(int i = 1; i <= n; i++)
position[str2[i - 1] - 'a'].Add(i);
int[,] lcsl = new int[m + 2, n + 2];
int[,] lcsr = new int[m + 2, n + 2];
// Initializing 2D array by 0 values
for(int i = 0; i <= m + 1; i++)
for(int j = 0; j <= n + 1; j++)
lcsl[i, j] = lcsr[i, j] = 0;
// Filling LCS array for prefix substrings
for(int i = 1; i <= m; i++)
{
for(int j = 1; j <= n; j++)
{
if (str1[i - 1] == str2[j - 1])
lcsl[i, j] = 1 + lcsl[i - 1, j - 1];
else
lcsl[i, j] = Math.Max(lcsl[i - 1, j],
lcsl[i, j - 1]);
}
}
// Filling LCS array for suffix substrings
for(int i = m; i >= 1; i--)
{
for(int j = n; j >= 1; j--)
{
if (str1[i - 1] == str2[j - 1])
lcsr[i, j] = 1 + lcsr[i + 1, j + 1];
else
lcsr[i, j] = Math.Max(lcsr[i + 1, j],
lcsr[i, j + 1]);
}
}
// Looping for all possible insertion
// positions in first string
int ways = 0;
for(int i = 0; i <= m; i++)
{
// Trying all possible lower
// case characters
for(int d = 0; d < 26; d++)
{
// Now for each character, loop over same
// character positions in second string
for(int j = 0; j < position[d].Count; j++)
{
int p = position[d][j];
// If both, left and right substrings make
// total LCS then increase result by 1
if (lcsl[i, p - 1] +
lcsr[i + 1, p + 1] == lcsl[m, n])
ways++;
}
}
}
return ways;
}
// Driver Code
public static void Main(String[] args)
{
String str1 = "abcabc";
String str2 = "abcd";
Console.WriteLine(waysToIncreaseLCSBy1(str1, str2));
}
}
// This code is contributed by Princi Singh
输出:
4
时间复杂度: O(mn)
辅助空间: O(mn)