没有重复字符的最长公共子序列
给定两个字符串s1和s2 ,任务是找出没有重复字符的最长公共子序列的长度。
例子:
Input: s1= “aabbcc”, s2= “aabc”
Output: 3
Explanation: “aabc” is longest common subsequence but it has two repeating character ‘a’.
So the required longest common subsequence with no repeating character is “abc”.
Input: s1= “aabcad”, s2= “adbcwcad”
Output: 4
Explanation: The subsequences are “abcd” or “bcad”.
方法:解决问题的方法类似于使用递归的最长公共子序列,但还需要跟踪子序列中没有两个字符重复。请按照以下步骤操作:
- 对于第 i 个位置的每个字符,该字符可以是序列的一部分,也可以不是。
- 以这种方式生成每个序列并检查最长的公共序列。
- 要跟踪子序列中包含哪些字符,请使用变量“store”的位。
- 变量“store”的每一位,告诉字母表是否已经存在于子序列中。
- 第 0 位对应字符'a',位置 1 对应 'b',类似 2 对应 'c',依此类推。
下面是上述方法的实现。
C++
// C++ program to implement the approach
#include
using namespace std;
// Function to find lcs
// with no repeating character
int find(string s1, string s2, int N,
int M, long long store)
{
if (N == 0 || M == 0)
return 0;
if (s1[N - 1] == s2[M - 1]
&& ((store >> (s1[N - 1] - 'a'))
& 1)
== 0) {
store = (store | (1 << (s1[N - 1]
- 'a')));
return 1 + find(s1, s2, N - 1,
M - 1, store);
}
else
return max(find(s1, s2, N - 1, M,
store),
find(s1, s2, N, M - 1,
store));
}
// Driver code
int main()
{
string s1, s2;
s1 = "aabbcc";
s2 = "aabc";
long long store = 0;
cout << find(s1, s2, s1.length(),
s2.length(), store);
return 0;
}
Java
// Java program for the above approach
class GFG {
// Function to find lcs
// with no repeating character
static int find(String s1, String s2, int N,
int M, int store) {
if (N == 0 || M == 0)
return 0;
if (s1.charAt(N - 1) == s2.charAt(M - 1)
&& ((store >> (s1.charAt(N - 1) - 'a'))
& 1) == 0) {
store = (store | (1 << (s1.charAt(N - 1) - 'a')));
return 1 + find(s1, s2, N - 1, M - 1, store);
}
else
return Math.max(find(s1, s2, N - 1, M, store),
find(s1, s2, N, M - 1, store));
}
// Driver Code
public static void main(String args[]) {
String s1, s2;
s1 = "aabbcc";
s2 = "aabc";
int store = 0;
System.out.println(find(s1, s2, s1.length(), s2.length(), store));
}
}
// This code is contributed by gfgking
Python3
# python3 program to implement the approach
# Function to find lcs
# with no repeating character
def find(s1, s2, N, M, store):
if (N == 0 or M == 0):
return 0
if (s1[N - 1] == s2[M - 1]
and ((store >> (ord(s1[N - 1]) - ord('a')))
& 1)
== 0):
store = (store | (1 << (ord(s1[N - 1]) - ord('a'))))
return 1 + find(s1, s2, N - 1,
M - 1, store)
else:
return max(find(s1, s2, N - 1, M,
store),
find(s1, s2, N, M - 1,
store))
# Driver code
if __name__ == "__main__":
s1 = "aabbcc"
s2 = "aabc"
store = 0
print(find(s1, s2, len(s1), len(s2), store))
# This code is contributed by rakeshsahni
C#
// C# program for the above approach
using System;
public class GFG
{
// Function to find lcs
// with no repeating character
static int find(string s1, string s2, int N,
int M, int store)
{
if (N == 0 || M == 0)
return 0;
if (s1[N - 1] == s2[M - 1]
&& ((store >> (s1[N - 1] - 'a'))
& 1)
== 0) {
store = (store | (1 << (s1[N - 1]
- 'a')));
return 1 + find(s1, s2, N - 1,
M - 1, store);
}
else
return Math.Max(find(s1, s2, N - 1, M,
store),
find(s1, s2, N, M - 1,
store));
}
// Driver Code
public static void Main(String[] args)
{
string s1, s2;
s1 = "aabbcc";
s2 = "aabc";
int store = 0;
Console.Write(find(s1, s2, s1.Length,
s2.Length, store));
}
}
// This code is contributed by code_hunt.
Javascript
C++
// C++ program to implement the approach
#include
using namespace std;
// Map for memoization
map mp;
// Function to find lcs
// with no repeating character
int find(string s1, string s2, int N, int M,
long long store)
{
if (N == 0 || M == 0)
return 0;
string temp = to_string(N) + '#'
+ to_string(M) + '#'
+ to_string(store);
if (mp.find(temp) != mp.end())
return mp[temp];
// If the characters are same
if (s1[N - 1] == s2[M - 1]
&& ((store >> (s1[N - 1] - 'a'))
& 1)
== 0) {
store = (store | (1 << (s1[N - 1]
- 'a')));
return mp[temp]
= 1 + find(s1, s2, N - 1,
M - 1, store);
}
// if the characters are different
else
return mp[temp]
= max(find(s1, s2, N - 1,
M, store),
find(s1, s2, N, M - 1,
store));
}
// Driver code
int main()
{
string s1, s2;
s1 = "aabbcc";
s2 = "aabc";
long long store = 0;
cout << find(s1, s2, s1.length(),
s2.length(), store);
return 0;
}
Python3
# Python3 program to implement the approach
# Map for memoization
mp = {}
# Function to find lcs
# with no repeating character
def find(s1,s2,N,M,store):
if (N == 0 or M == 0):
return 0
temp = str(N) + '#' + str(M) + '#' + str(store)
if(temp in mp):
return mp[temp]
# If the characters are same
if (s1[N - 1] == s2[M - 1] and ((store >> (ord(s1[N - 1]) - ord('a'))) & 1)== 0):
store = (store | (1 << (ord(s1[N - 1]) - ord('a'))))
mp[temp] = 1 + find(s1, s2, N - 1,M - 1, store)
return mp[temp]
# if the characters are different
else:
mp[temp] = max(find(s1, s2, N - 1,M, store),find(s1, s2, N, M - 1,store))
return mp[temp]
# Driver code
s1 = "aabbcc"
s2 = "aabc"
store = 0
print(find(s1, s2, len(s1),len(s2), store))
# This code is contributed by shinjanpatra
C#
// C# program to implement the approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG {
// Map for memoization
static Dictionary mp
= new Dictionary();
// Function to find lcs
// with no repeating character
static int find(string s1, string s2, int N, int M,
long store)
{
if (N == 0 || M == 0)
return 0;
string temp = N.ToString() + '#' + M.ToString()
+ '#' + store.ToString();
if (mp.ContainsKey(temp)) {
return mp[temp];
}
// If the characters are same
if (s1[N - 1] == s2[M - 1]
&& ((store >> (s1[N - 1] - 'a')) & 1) == 0) {
store = (store | (1 << (s1[N - 1] - 'a')));
return mp[temp]
= 1 + find(s1, s2, N - 1, M - 1, store);
}
// if the characters are different
else
return mp[temp]
= Math.Max(find(s1, s2, N - 1, M, store),
find(s1, s2, N, M - 1, store));
}
// Driver code
public static void Main()
{
string s1 = "aabbcc";
string s2 = "aabc";
long store = 0;
Console.Write(
find(s1, s2, s1.Length, s2.Length, store));
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
3
时间复杂度: O(N * 2 N ),其中 N 是最大值(s1 的大小,s2 的大小)。
辅助空间: O(1)
高效方法:一种有效的方法是使用记忆化来降低时间复杂度。创建一个 2D dp[][] 数组,其中dp[i][j]存储最长公共子序列的长度,直到考虑s1的第i个索引和s2的第 j 个索引,没有重复字符。如果s1[i]和s2[j]处的字符相同,则dp[i][j] = dp[i-1][j-1] + 1 ,否则dp[i][j] = max(dp[ i-1][j],dp[i][j-1]) 。只需跟踪上述方法中提到的重复字符即可。
注意:在实现中, dp数组是使用 map 实现的,其中键是i和j的串联字符串。
下面给出的是上述方法的实现。
C++
// C++ program to implement the approach
#include
using namespace std;
// Map for memoization
map mp;
// Function to find lcs
// with no repeating character
int find(string s1, string s2, int N, int M,
long long store)
{
if (N == 0 || M == 0)
return 0;
string temp = to_string(N) + '#'
+ to_string(M) + '#'
+ to_string(store);
if (mp.find(temp) != mp.end())
return mp[temp];
// If the characters are same
if (s1[N - 1] == s2[M - 1]
&& ((store >> (s1[N - 1] - 'a'))
& 1)
== 0) {
store = (store | (1 << (s1[N - 1]
- 'a')));
return mp[temp]
= 1 + find(s1, s2, N - 1,
M - 1, store);
}
// if the characters are different
else
return mp[temp]
= max(find(s1, s2, N - 1,
M, store),
find(s1, s2, N, M - 1,
store));
}
// Driver code
int main()
{
string s1, s2;
s1 = "aabbcc";
s2 = "aabc";
long long store = 0;
cout << find(s1, s2, s1.length(),
s2.length(), store);
return 0;
}
Python3
# Python3 program to implement the approach
# Map for memoization
mp = {}
# Function to find lcs
# with no repeating character
def find(s1,s2,N,M,store):
if (N == 0 or M == 0):
return 0
temp = str(N) + '#' + str(M) + '#' + str(store)
if(temp in mp):
return mp[temp]
# If the characters are same
if (s1[N - 1] == s2[M - 1] and ((store >> (ord(s1[N - 1]) - ord('a'))) & 1)== 0):
store = (store | (1 << (ord(s1[N - 1]) - ord('a'))))
mp[temp] = 1 + find(s1, s2, N - 1,M - 1, store)
return mp[temp]
# if the characters are different
else:
mp[temp] = max(find(s1, s2, N - 1,M, store),find(s1, s2, N, M - 1,store))
return mp[temp]
# Driver code
s1 = "aabbcc"
s2 = "aabc"
store = 0
print(find(s1, s2, len(s1),len(s2), store))
# This code is contributed by shinjanpatra
C#
// C# program to implement the approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG {
// Map for memoization
static Dictionary mp
= new Dictionary();
// Function to find lcs
// with no repeating character
static int find(string s1, string s2, int N, int M,
long store)
{
if (N == 0 || M == 0)
return 0;
string temp = N.ToString() + '#' + M.ToString()
+ '#' + store.ToString();
if (mp.ContainsKey(temp)) {
return mp[temp];
}
// If the characters are same
if (s1[N - 1] == s2[M - 1]
&& ((store >> (s1[N - 1] - 'a')) & 1) == 0) {
store = (store | (1 << (s1[N - 1] - 'a')));
return mp[temp]
= 1 + find(s1, s2, N - 1, M - 1, store);
}
// if the characters are different
else
return mp[temp]
= Math.Max(find(s1, s2, N - 1, M, store),
find(s1, s2, N, M - 1, store));
}
// Driver code
public static void Main()
{
string s1 = "aabbcc";
string s2 = "aabc";
long store = 0;
Console.Write(
find(s1, s2, s1.Length, s2.Length, store));
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
3
时间复杂度: O(N * M) 其中 N 是 s1 的大小,M 是 s2 的大小
辅助空间: O(N * M)