Open In App

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:

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.

Algorithm:

  1. Create two vectors of strings, one for the source words (sw) and one for the target words (tw).
  2. Create an unordered set of strings to store the sorted permutations of the source words.
  3. 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.
  4. Initialize a variable “ans” to 0, which will store the number of target words that can be formed.
  5. Loop through each word in the target words vector.
  6. Sort the characters in the target word and store it in a string variable “test”.
  7. Initialize a boolean variable “check” to false, which will be used to track if a valid word can be formed from the target word.
  8. Loop through each character in the target word.
  9. Create a new string “search” by removing the character at index j from the sorted target word.
  10. Check if “search” is present in the unordered set of sorted source words.
  11. If “search” is present in the set, set “check” to true and break out of the loop.
  12. If “check” is true, increment “and”.
  13. Return “ans”.

Below is the implementation of the above approach.




// 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 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 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# 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




<script>
 
// 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
 
</script>

Output
1




Time Complexity: O(N*M) where N and M are the size of SearchWord[] and FindWord[]
Auxiliary Space: O(N)

Another Approach:

Below is the implementation of the above approach:




#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




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);
    }
}




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)




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);
    }
}




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);

Output
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)


Article Tags :