Given two strings s1 and s2. Check whether they contain any common subsequence (non empty) or not.
Examples:
Input: s1 = "ABEF", s2 = "CADE"
Output: true
Explanation: Subsequence "AE" occurs in both the strings.
Input: s1 = "ABCD", s2 = "EFGH"
Output: false
Explanation: There's no common subsequence in both the strings.
Table of Content
[Naive Approach] Generate All Subsequences - O(2^|s1| + 2^|s2|) Time O(2^|s1|) Space
- Generate all possible non-empty subsequences of the first string using recursion and store them in a hash set for quick lookup.
- Generate all subsequences of the second string and check whether any of them already exists in the hash set.
- If a matching subsequence is found, it means both strings contain a common subsequence, so return
true.
#include <bits/stdc++.h>
using namespace std;
// Generate all subsequences
void generateSubseq(string &s, int idx, string curr, unordered_set<string> &st)
{
// Store non-empty subsequence
if (!curr.empty())
st.insert(curr);
if (idx == s.length())
return;
for (int i = idx; i < s.length(); i++)
{
generateSubseq(s, i + 1, curr + s[i], st);
}
}
// Check subsequences of second string
bool checkSubseq(string &s, int idx, string curr, unordered_set<string> &st)
{
if (!curr.empty() && st.find(curr) != st.end())
return true;
if (idx == s.length())
return false;
for (int i = idx; i < s.length(); i++)
{
if (checkSubseq(s, i + 1, curr + s[i], st))
return true;
}
return false;
}
bool commonSubseq(string &s1, string &s2)
{
unordered_set<string> st;
// Generate subsequences of first string
generateSubseq(s1, 0, "", st);
// Check subsequences of second string
return checkSubseq(s2, 0, "", st);
}
// Driver Code
int main()
{
string s1 = "ABEF";
string s2 = "CADE";
if (commonSubseq(s1, s2))
cout << "true";
else
cout << "false";
return 0;
}
import java.util.HashSet;
import java.util.Set;
public class GfG {
// Generate all subsequences
static void generateSubseq(String s, int idx, String curr, Set<String> st) {
// Store non-empty subsequence
if (!curr.isEmpty())
st.add(curr);
if (idx == s.length())
return;
for (int i = idx; i < s.length(); i++)
generateSubseq(s, i + 1, curr + s.charAt(i), st);
}
// Check subsequences of second string
static boolean checkSubseq(String s, int idx, String curr, Set<String> st) {
if (!curr.isEmpty() && st.contains(curr))
return true;
if (idx == s.length())
return false;
for (int i = idx; i < s.length(); i++)
if (checkSubseq(s, i + 1, curr + s.charAt(i), st))
return true;
return false;
}
static boolean commonSubseq(String s1, String s2) {
Set<String> st = new HashSet<>();
// Generate subsequences of first string
generateSubseq(s1, 0, "", st);
// Check subsequences of second string
return checkSubseq(s2, 0, "", st);
}
public static void main(String[] args) {
String s1 = "ABEF";
String s2 = "CADE";
if (commonSubseq(s1, s2))
System.out.println("true");
else
System.out.println("false");
}
}
from typing import Set
# Generate all subsequences
def generateSubseq(s: str, idx: int, curr: str, st: Set[str]) -> None:
# Store non-empty subsequence
if curr:
st.add(curr)
if idx == len(s):
return
for i in range(idx, len(s)):
generateSubseq(s, i + 1, curr + s[i], st)
# Check subsequences of second string
def checkSubseq(s: str, idx: int, curr: str, st: Set[str]) -> bool:
if curr and curr in st:
return True
if idx == len(s):
return False
for i in range(idx, len(s)):
if checkSubseq(s, i + 1, curr + s[i], st):
return True
return False
def commonSubseq(s1: str, s2: str) -> bool:
st: Set[str] = set()
# Generate subsequences of first string
generateSubseq(s1, 0, "", st)
# Check subsequences of second string
return checkSubseq(s2, 0, "", st)
# Driver Code
if __name__ == "__main__":
s1 = "ABEF"
s2 = "CADE"
if commonSubseq(s1, s2):
print("true")
else:
print("false")
using System;
using System.Collections.Generic;
class GfG
{
// Generate all subsequences
static void generateSubseq(string s, int idx, string curr, HashSet<string> st)
{
// Store non-empty subsequence
if (!string.IsNullOrEmpty(curr))
st.Add(curr);
if (idx == s.Length)
return;
for (int i = idx; i < s.Length; i++)
{
generateSubseq(s, i + 1, curr + s[i], st);
}
}
// Check subsequences of second string
static bool checkSubseq(string s, int idx, string curr, HashSet<string> st)
{
if (!string.IsNullOrEmpty(curr) && st.Contains(curr))
return true;
if (idx == s.Length)
return false;
for (int i = idx; i < s.Length; i++)
{
if (checkSubseq(s, i + 1, curr + s[i], st))
return true;
}
return false;
}
static bool commonSubseq(string s1, string s2)
{
HashSet<string> st = new HashSet<string>();
// Generate subsequences of first string
generateSubseq(s1, 0, "", st);
// Check subsequences of second string
return checkSubseq(s2, 0, "", st);
}
// Driver Code
static void Main()
{
string s1 = "ABEF";
string s2 = "CADE";
if (commonSubseq(s1, s2))
Console.WriteLine("true");
else
Console.WriteLine("false");
}
}
function generateSubseq(s, idx, curr, st) {
// Store non-empty subsequence
if (curr.length > 0) {
st.add(curr);
}
if (idx === s.length) {
return;
}
for (let i = idx; i < s.length; i++) {
generateSubseq(s, i + 1, curr + s[i], st);
}
}
function checkSubseq(s, idx, curr, st) {
if (curr.length > 0 && st.has(curr)) {
return true;
}
if (idx === s.length) {
return false;
}
for (let i = idx; i < s.length; i++) {
if (checkSubseq(s, i + 1, curr + s[i], st)) {
return true;
}
}
return false;
}
function commonSubseq(s1, s2) {
let st = new Set();
// Generate subsequences of first string
generateSubseq(s1, 0, "", st);
// Check subsequences of second string
return checkSubseq(s2, 0, "", st);
}
// Driver Code
let s1 = "ABEF";
let s2 = "CADE";
if (commonSubseq(s1, s2)) {
console.log("true");
} else {
console.log("false");
}
Output
true
Time Complexity: O(2^|s1| + 2^|s2|)
Auxiliary Space: O(2^|s1|)
[Expected Approach] Check Common Character - O(|s1| + |s2|) Time O(1) Space
The idea is that even a single common character between the two strings forms a common subsequence of length 1.
We store the presence of all characters of the first string in a frequency array. Then we traverse the second string and check whether any character is already marked present. If a common character is found, return true; otherwise, return false.
#include <bits/stdc++.h>
using namespace std;
bool commonSubseq(string &s1, string &s2)
{
// Frequency array for characters
vector<int> freq(256, 0);
// Mark characters of first string
for (char ch : s1)
freq[ch] = 1;
// Check characters in second string
for (char ch : s2)
{
// Common character found
if (freq[ch])
return true;
}
return false;
}
// Driver Code
int main()
{
string s1 = "ABEF";
string s2 = "CADE";
if (commonSubseq(s1, s2))
cout << "true";
else
cout << "false";
return 0;
}
import java.util.Arrays;
public class GfG {
public static boolean commonSubseq(String s1, String s2) {
// Frequency array for characters
int[] freq = new int[256];
// Mark characters of first string
for (char ch : s1.toCharArray())
freq[ch] = 1;
// Check characters in second string
for (char ch : s2.toCharArray()) {
// Common character found
if (freq[ch] == 1)
return true;
}
return false;
}
public static void main(String[] args) {
String s1 = "ABEF";
String s2 = "CADE";
if (commonSubseq(s1, s2))
System.out.println("true");
else
System.out.println("false");
}
}
def commonSubseq(s1, s2):
# Frequency array for characters
freq = [0] * 256
# Mark characters of first string
for ch in s1:
freq[ord(ch)] = 1
# Check characters in second string
for ch in s2:
# Common character found
if freq[ord(ch)]:
return True
return False
# Driver Code
if __name__ == "__main__":
s1 = "ABEF"
s2 = "CADE"
if commonSubseq(s1, s2):
print("true")
else:
print("false")
using System;
public class GfG
{
public static bool commonSubseq(string s1, string s2)
{
// Frequency array for characters
int[] freq = new int[256];
// Mark characters of first string
foreach (char ch in s1)
freq[ch] = 1;
// Check characters in second string
foreach (char ch in s2)
{
// Common character found
if (freq[ch] == 1)
return true;
}
return false;
}
public static void Main()
{
string s1 = "ABEF";
string s2 = "CADE";
if (commonSubseq(s1, s2))
Console.WriteLine("true");
else
Console.WriteLine("false");
}
}
function commonSubseq(s1, s2) {
// Frequency array for characters
let freq = new Array(256).fill(0);
// Mark characters of first string
for (let ch of s1) {
freq[ch.charCodeAt(0)] = 1;
}
// Check characters in second string
for (let ch of s2) {
// Common character found
if (freq[ch.charCodeAt(0)] === 1) {
return true;
}
}
return false;
}
// Driver Code
let s1 = "ABEF";
let s2 = "CADE";
if (commonSubseq(s1, s2)) {
console.log('true');
} else {
console.log('false');
}
Output
true
Time Complexity: O(|s1| + |s2|)
Auxiliary Space: O(1)