Count of strings in Array A that can be made equal to strings in Array B by appending characters
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++
// C++ code to implement the above approach #include <bits/stdc++.h> using namespace std; // Function to find permutation 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; // Loop to check how many string // can be formed for ( int i = 0; i < tw.size(); i++) { string test = tw[i]; sort(test.begin(), test.end()); // To track the number // Of the words formed bool check = 0; for ( int j = 0; j < test.size(); j++) { // Substring from 0 to 'i' // and remove one alphabet // and append rest of the string string search = test.substr(0, j) + test.substr(j + 1); // Check if the word is available // in the set if (s.find(search) != s.end()) { check = 1; break ; } } if (check) ans++; } return ans; } // Driver Code int main() { vector<string> str = { "ohr" , "tm" , "ek" }; vector<string> str1 = { "mat" , "hr" }; cout << solution(str, str1); return 0; } |
Java
// Java code to implement the above approach import java.util.*; class GFG{ // Function to find permutation 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 ; // Loop to check how many String // can be formed for ( int i = 0 ; i < tw.length; i++) { String test = tw[i]; test = sort(test); // To track the number // Of the words formed boolean check = false ; for ( int j = 0 ; j < test.length(); j++) { // SubString from 0 to 'i' // and remove one alphabet // and append rest of the String String search = test.substring( 0 , j) + test.substring(j + 1 ); // Check if the word is available // in the set if (s.contains(search)) { check = true ; break ; } } if (check) ans++; } return ans; } //Method to sort a string alphabetically static String sort(String inputString) { // convert input string to char array char tempArray[] = inputString.toCharArray(); // sort tempArray Arrays.sort(tempArray); // return new sorted string return new String(tempArray); } // Driver Code public static void main(String[] args) { String[] str = { "ohr" , "tm" , "ek" }; String[] str1 = { "mat" , "hr" }; System.out.print(solution(str, str1)); } } // This code is contributed by shikhasingrajput |
Python3
# python3 code to implement the above approach # Function to find permutation def solution(sw, tw): s = set () for i in range ( 0 , len (sw)): s.add("".join( sorted ( list (sw[i])))) ans = 0 # Loop to check how many string # can be formed for i in range ( 0 , len (tw)): test = "".join( sorted ( list (tw[i]))) # To track the number # Of the words formed check = 0 for j in range ( 0 , len (test)): # Substring from 0 to 'i' # and remove one alphabet # and append rest of the string search = test[:j] + test[j + 1 :] # Check if the word is available # in the set if (search in s): check = 1 break if (check): ans + = 1 return ans # Driver Code if __name__ = = "__main__" : str = [ "ohr" , "tm" , "ek" ] str1 = [ "mat" , "hr" ] print (solution( str , str1)) # This code is contributed by rakeshsahni |
C#
// C# code to implement the above approach using System; using System.Collections.Generic; public class GFG{ // Function to find permutation 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; // Loop to check how many String // can be formed for ( int i = 0; i < tw.Length; i++) { String test = tw[i]; test = sort(test); // To track the number // Of the words formed bool check = false ; for ( int j = 0; j < test.Length; j++) { // SubString from 0 to 'i' // and remove one alphabet // and append rest of the String String search = test.Substring(0, j) + test.Substring(j + 1); // Check if the word is available // in the set if (s.Contains(search)) { check = true ; break ; } } if (check) ans++; } return ans; } //Method to sort a string alphabetically static String sort(String inputString) { // convert input string to char array char []tempArray = inputString.ToCharArray(); // sort tempArray Array.Sort(tempArray); // return new sorted string return new String(tempArray); } // Driver Code public static void Main(String[] args) { String[] str = { "ohr" , "tm" , "ek" }; String[] str1 = { "mat" , "hr" }; Console.Write(solution(str, str1)); } } // This code is contributed by 29AjayKumar |
Javascript
// JavaScript code to implement the above approach // Function to find permutation 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; // Loop to check how many string // can be formed for (let i = 0; i < tw.length; i++) { let test = tw[i]; test = test.split( "" ).sort().join( "" ); // To track the number // Of the words formed let check = 0; for (let j = 0; j < test.length; j++) { // Substring from 0 to 'i' // and remove one alphabet // and append rest of the string let search = test.substring(0, j) + test.substring(j + 1); // Check if the word is available // in the set if (s.has(search)) { check = 1; break ; } } if (check) ans++; } return ans; } // Driver Code let str = [ "ohr" , "tm" , "ek" ]; let str1 = [ "mat" , "hr" ]; document.write(solution(str, str1)); // This code is contributed by shinjanpatra |
1
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; // Create frequency arrays for each string in SearchWord[] vector<vector< int >> freq(n, vector< int >(26, 0)); for ( int i = 0; i < n; i++) { for ( char c : SearchWord[i]) { freq[i]++; } } // Check if each string in FindWord[] can be formed by adding one alphabet and rearranging the string vector< bool > found(m, false ); for ( int i = 0; i < m; i++) { // Create frequency array for the current string in FindWord[] vector< int > f(26, 0); for ( char c : FindWord[i]) { f++; } // Iterate through all the strings in SearchWord[] for ( int j = 0; j < n; j++) { bool possible = true ; int diff = 0; // Check if it is possible to form the current string in FindWord[] from the current string in SearchWord[] 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 ; } } } // Count the number of strings that were found for ( bool f : found) { if (f) { count++; } } cout << count << endl; return 0; } // This code is contributed by rudra1807raj |
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 ; // Initialize a 2D array to store character // frequency for each word in SearchWord int [][] freq = new int [n][ 26 ]; // Calculate character frequency for each word in // SearchWord for ( int i = 0 ; i < n; i++) { for ( char c : SearchWord[i].toCharArray()) { freq[i]++; } } // Initialize an array to track whether a word in // FindWord matches any word in SearchWord boolean [] found = new boolean [m]; // Iterate through each word in FindWord for ( int i = 0 ; i < m; i++) { // Initialize an array to store character // frequency for the current word in FindWord int [] f = new int [ 26 ]; // Calculate character frequency for the current // word in FindWord for ( char c : FindWord[i].toCharArray()) { f++; } // Iterate through each word in SearchWord to // find a match for ( int j = 0 ; j < n; j++) { boolean possible = true ; int diff = 0 ; // Compare character frequencies of the // current word in FindWord and the current // word in SearchWord 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 ; } } } // Check if the current word in FindWord // matches the current word in SearchWord if (possible && diff == 1 ) { found[i] = true ; break ; } } } // Count the number of matching words 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; // Create frequency arrays for each string in SearchWord[] 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); } // Check if each string in FindWord[] can be formed by adding one alphabet and rearranging the string bool [] found = new bool [m]; for ( int i = 0; i < m; i++) { // Create a frequency array for the current string in FindWord[] int [] f = new int [26]; foreach ( char c in FindWord[i]) { f++; } // Iterate through all the strings in SearchWord[] for ( int j = 0; j < n; j++) { bool possible = true ; int diff = 0; // Check if it is possible to form the current string in FindWord[] from the current string in SearchWord[] 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 ; } } } // Count the number of strings that were found 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); |
1
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)