Given two arrays of strings SearchWord[] and FindWord[]. The task is to check how many strings in FindWord[] can be formed after the following operations on as many strings as possible:
- Pick a string from SearchWord[].
- Add one English alphabet (that is not present in that string).
- Rearrange the string as you like.
Note: Every alphabet in the SearchWord[] and in the FindWord[] are unique and appear only once.
Examples:
Input: SearchWord = {“ge”, “fo”, “ek”}, FindWord = {“gek”, “for”}
Output: 2
Explanation: ‘k’ can be appended to the “ge” to make “gek” which matches the FindWord[0]
‘r’ can be appended to the “fo” to make “for” which matches the FindWord[1]
Input: SearchWord = {“ohr”, “tm”, “ek”}, FindWord = {“mat”, “hr”}
Output: 1
Approach: The simple approach to solving this problem is by sorting and using hashing technique.
- Sort SearchWord[] and FindWord[] in Alphabetical order.
- Apply the reverse logic rather than picking a word from the SearchWord[] array, pick the word from the FindWord[] array.
- And search that word by removing the character one by one and finding the Matching word.
Algorithm:
- Create two vectors of strings, one for the source words (sw) and one for the target words (tw).
- Create an unordered set of strings to store the sorted permutations of the source words.
- Loop through each word in the source words vector and sort the characters in each word. Then, insert the sorted word into the unordered set.
- Initialize a variable “ans” to 0, which will store the number of target words that can be formed.
- Loop through each word in the target words vector.
- Sort the characters in the target word and store it in a string variable “test”.
- Initialize a boolean variable “check” to false, which will be used to track if a valid word can be formed from the target word.
- Loop through each character in the target word.
- Create a new string “search” by removing the character at index j from the sorted target word.
- Check if “search” is present in the unordered set of sorted source words.
- If “search” is present in the set, set “check” to true and break out of the loop.
- If “check” is true, increment “and”.
- Return “ans”.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int solution(vector<string>& sw,
vector<string>& tw)
{
unordered_set<string> s;
for ( int i = 0; i < sw.size(); i++) {
sort(sw[i].begin(), sw[i].end());
s.insert(sw[i]);
}
int ans = 0;
for ( int i = 0; i < tw.size(); i++) {
string test = tw[i];
sort(test.begin(), test.end());
bool check = 0;
for ( int j = 0; j < test.size(); j++) {
string search
= test.substr(0, j)
+ test.substr(j + 1);
if (s.find(search) != s.end()) {
check = 1;
break ;
}
}
if (check)
ans++;
}
return ans;
}
int main()
{
vector<string> str = { "ohr" , "tm" , "ek" };
vector<string> str1 = { "mat" , "hr" };
cout << solution(str, str1);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int solution(String[] sw,
String[] tw)
{
HashSet<String> s = new HashSet<>();
for ( int i = 0 ; i < sw.length; i++) {
sw[i] = sort(sw[i]);
s.add(sw[i]);
}
int ans = 0 ;
for ( int i = 0 ; i < tw.length; i++) {
String test = tw[i];
test = sort(test);
boolean check = false ;
for ( int j = 0 ; j < test.length(); j++) {
String search
= test.substring( 0 , j)
+ test.substring(j + 1 );
if (s.contains(search)) {
check = true ;
break ;
}
}
if (check)
ans++;
}
return ans;
}
static String sort(String inputString)
{
char tempArray[] = inputString.toCharArray();
Arrays.sort(tempArray);
return new String(tempArray);
}
public static void main(String[] args)
{
String[] str = { "ohr" , "tm" , "ek" };
String[] str1 = { "mat" , "hr" };
System.out.print(solution(str, str1));
}
}
|
Python3
def solution(sw, tw):
s = set ()
for i in range ( 0 , len (sw)):
s.add("".join( sorted ( list (sw[i]))))
ans = 0
for i in range ( 0 , len (tw)):
test = "".join( sorted ( list (tw[i])))
check = 0
for j in range ( 0 , len (test)):
search = test[:j] + test[j + 1 :]
if (search in s):
check = 1
break
if (check):
ans + = 1
return ans
if __name__ = = "__main__" :
str = [ "ohr" , "tm" , "ek" ]
str1 = [ "mat" , "hr" ]
print (solution( str , str1))
|
C#
using System;
using System.Collections.Generic;
public class GFG{
static int solution(String[] sw,
String[] tw)
{
HashSet<String> s = new HashSet<String>();
for ( int i = 0; i < sw.Length; i++) {
sw[i] = sort(sw[i]);
s.Add(sw[i]);
}
int ans = 0;
for ( int i = 0; i < tw.Length; i++) {
String test = tw[i];
test = sort(test);
bool check = false ;
for ( int j = 0; j < test.Length; j++) {
String search
= test.Substring(0, j)
+ test.Substring(j + 1);
if (s.Contains(search)) {
check = true ;
break ;
}
}
if (check)
ans++;
}
return ans;
}
static String sort(String inputString)
{
char []tempArray = inputString.ToCharArray();
Array.Sort(tempArray);
return new String(tempArray);
}
public static void Main(String[] args)
{
String[] str = { "ohr" , "tm" , "ek" };
String[] str1 = { "mat" , "hr" };
Console.Write(solution(str, str1));
}
}
|
Javascript
<script>
function solution(sw,tw)
{
let s = new Set();
for (let i = 0; i < sw.length; i++) {
sw[i] = sw[i].split( "" ).sort().join( "" );
s.add(sw[i]);
}
let ans = 0;
for (let i = 0; i < tw.length; i++) {
let test = tw[i];
test = test.split( "" ).sort().join( "" );
let check = 0;
for (let j = 0; j < test.length; j++) {
let search = test.substring(0, j) + test.substring(j + 1);
if (s.has(search)) {
check = 1;
break ;
}
}
if (check)
ans++;
}
return ans;
}
let str = [ "ohr" , "tm" , "ek" ];
let str1 = [ "mat" , "hr" ];
document.write(solution(str, str1));
</script>
|
Time Complexity: O(N*M) where N and M are the size of SearchWord[] and FindWord[]
Auxiliary Space: O(N)
Another Approach:
- Create a frequency array for each string in SearchWord[], which counts the frequency of each alphabet in the string.
- For each string in FindWord[], create a frequency array as well.
- For each string in FindWord[], iterate through all the strings in SearchWord[] and check if it is possible to form the string by adding one alphabet and rearranging the string. This can be done by checking if the frequency arrays are the same, except for one alphabet that has a frequency of 1 in the FindWord[] frequency array and 0 in the SearchWord[] frequency array.
- If a string in FindWord[] can be formed, mark it as found and move on to the next string in FindWord[].
- Count the number of strings that were found and return the count as the output.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> SearchWord = { "ohr" , "tm" , "ek" };
vector<string> FindWord = { "mat" , "hr" };
int n = SearchWord.size();
int m = FindWord.size();
int count = 0;
vector<vector< int >> freq(n, vector< int >(26, 0));
for ( int i = 0; i < n; i++) {
for ( char c : SearchWord[i]) {
freq[i]++;
}
}
vector< bool > found(m, false );
for ( int i = 0; i < m; i++) {
vector< int > f(26, 0);
for ( char c : FindWord[i]) {
f++;
}
for ( int j = 0; j < n; j++) {
bool possible = true ;
int diff = 0;
for ( int k = 0; k < 26; k++) {
if (f[k] != freq[j][k]) {
if (f[k] == freq[j][k] + 1) {
diff++;
} else {
possible = false ;
break ;
}
}
}
if (possible && diff == 1) {
found[i] = true ;
break ;
}
}
}
for ( bool f : found) {
if (f) {
count++;
}
}
cout << count << endl;
return 0;
}
|
Java
public class Main {
public static void main(String[] args)
{
String[] SearchWord = { "ohr" , "tm" , "ek" };
String[] FindWord = { "mat" , "hr" };
int n = SearchWord.length;
int m = FindWord.length;
int count = 0 ;
int [][] freq = new int [n][ 26 ];
for ( int i = 0 ; i < n; i++) {
for ( char c : SearchWord[i].toCharArray()) {
freq[i]++;
}
}
boolean [] found = new boolean [m];
for ( int i = 0 ; i < m; i++) {
int [] f = new int [ 26 ];
for ( char c : FindWord[i].toCharArray()) {
f++;
}
for ( int j = 0 ; j < n; j++) {
boolean possible = true ;
int diff = 0 ;
for ( int k = 0 ; k < 26 ; k++) {
if (f[k] != freq[j][k]) {
if (f[k] == freq[j][k] + 1 ) {
diff++;
}
else {
possible = false ;
break ;
}
}
}
if (possible && diff == 1 ) {
found[i] = true ;
break ;
}
}
}
for ( boolean f : found) {
if (f) {
count++;
}
}
System.out.println(count);
}
}
|
Python3
SearchWord = [ "ohr" , "tm" , "ek" ]
FindWord = [ "mat" , "hr" ]
n = len (SearchWord)
m = len (FindWord)
count = 0
freq = [[ 0 ] * 26 for _ in range (n)]
for i in range (n):
for c in SearchWord[i]:
freq[i][ ord (c) - ord ( 'a' )] + = 1
found = [ False ] * m
for i in range (m):
f = [ 0 ] * 26
for c in FindWord[i]:
f[ ord (c) - ord ( 'a' )] + = 1
for j in range (n):
possible = True
diff = 0
for k in range ( 26 ):
if f[k] ! = freq[j][k]:
if f[k] = = freq[j][k] + 1 :
diff + = 1
else :
possible = False
break
if possible and diff = = 1 :
found[i] = True
break
for f in found:
if f:
count + = 1
print (count)
|
C#
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List< string > SearchWord = new List< string > { "ohr" , "tm" , "ek" };
List< string > FindWord = new List< string > { "mat" , "hr" };
int n = SearchWord.Count;
int m = FindWord.Count;
int count = 0;
List< int []> freq = new List< int []>();
for ( int i = 0; i < n; i++)
{
int [] charCount = new int [26];
foreach ( char c in SearchWord[i])
{
charCount++;
}
freq.Add(charCount);
}
bool [] found = new bool [m];
for ( int i = 0; i < m; i++)
{
int [] f = new int [26];
foreach ( char c in FindWord[i])
{
f++;
}
for ( int j = 0; j < n; j++)
{
bool possible = true ;
int diff = 0;
for ( int k = 0; k < 26; k++)
{
if (f[k] != freq[j][k])
{
if (f[k] == freq[j][k] + 1)
{
diff++;
}
else
{
possible = false ;
break ;
}
}
}
if (possible && diff == 1)
{
found[i] = true ;
break ;
}
}
}
foreach ( bool f in found)
{
if (f)
{
count++;
}
}
Console.WriteLine(count);
}
}
|
Javascript
const SearchWord = [ "ohr" , "tm" , "ek" ];
const FindWord = [ "mat" , "hr" ];
const n = SearchWord.length;
const m = FindWord.length;
let count = 0;
const freq = Array.from({ length: n }, () => Array(26).fill(0));
for (let i = 0; i < n; i++) {
for (let j = 0; j < SearchWord[i].length; j++) {
freq[i][SearchWord[i].charCodeAt(j) - 'a' .charCodeAt(0)] += 1;
}
}
const found = Array(m).fill( false );
for (let i = 0; i < m; i++) {
const f = Array(26).fill(0);
for (let j = 0; j < FindWord[i].length; j++) {
f[FindWord[i].charCodeAt(j) - 'a' .charCodeAt(0)] += 1;
}
for (let j = 0; j < n; j++) {
let possible = true ;
let diff = 0;
for (let k = 0; k < 26; k++) {
if (f[k] !== freq[j][k]) {
if (f[k] === freq[j][k] + 1) {
diff += 1;
} else {
possible = false ;
break ;
}
}
}
if (possible && diff === 1) {
found[i] = true ;
break ;
}
}
}
for (const f of found) {
if (f) {
count += 1;
}
}
console.log(count);
|
Time complexity: O(n*m), where n is the number of strings in SearchWord[] and m is the number of strings in FindWord[].
Auxiliary Space: O(n*26 + m*26)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
09 Nov, 2023
Like Article
Save Article