📜  没有重复字符的最长公共子序列

📅  最后修改于: 2022-05-13 01:56:08.713000             🧑  作者: Mango

没有重复字符的最长公共子序列

给定两个字符串s1s2 ,任务是找出没有重复字符的最长公共子序列的长度。

例子:

方法:解决问题的方法类似于使用递归的最长公共子序列,但还需要跟踪子序列中没有两个字符重复。请按照以下步骤操作:

  • 对于第 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 实现的,其中键是ij的串联字符串。

下面给出的是上述方法的实现。

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)