Skip to content
Related Articles

Related Articles

Improve Article

Search a string in the dictionary with a given prefix and suffix for Q queries

  • Difficulty Level : Hard
  • Last Updated : 10 Jul, 2021

Given an array arr[] consisting of N strings and Q queries in form of two strings prefix and suffix, the task for each query is to find any one string in the given array with the given prefix and suffix. If there exists no such string then print “-1”.

Examples:

Input: arr[] = {“apple”, “app”, “biscuit”, “mouse”, “orange”, “bat”, “microphone”, “mine”}, Queries[] = {{a, e}, {a, p}}
Output:
apple
app
Explanation:
Query 1: String “apple” is the only word in the given dictionary with the given prefix “a” and suffix “e”.
Query 2: String “app” is the only word in the given dictionary with the given prefix “a” and suffix “p”.

Input: arr[] = {“apple”, “app”, “biscuit”, “mouse”, “orange”, “bat”, “microphone”, “mine”}, Queries[] = {{mi, ne}}
Output: mine

Naive Approach: The simplest approach to solve the given problem is to traverse the given array of strings arr[] for each query and if there exists any such string with the given prefix and suffix, then print that string. Otherwise, print “-1”.



Time Complexity: O(Q*N*M), where M is the maximum length of the string.
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized by using the Trie Data Structure to solve the problem. The implementation of trie can be modified to support both prefix and suffix search in the following way:

  • Suppose the given word in a dictionary is apple. In this case, the word apple is inserted in the Trie. But to support prefix and suffix search simultaneously the words: e{apple, le{apple, ple{apple, pple{apple, apple{apple can be inserted in the Trie. 
  • Note that these words are of the form suffix{word where suffix is the all suffixes possible from the given word.
  • The special character { is inserted between the suffix and word to separate them. Any special character other than the alphabets can be used in place of {, but { is preferred because its ASCII value is 123 which is one more than the ASCII value of z.

Follow the steps below to solve the problem:

Below is the implementation of the above approach:

C++




// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Trie Node
struct Trie {
    Trie* arr[27] = { NULL };
  
    // Stores the index of the word
    // in the dictionary
    int idx;
};
  
// Root node of the Trie
Trie* root = new Trie();
  
// Function to insert the words in
// the Trie
void insert(string word, int i)
{
    // Temporary pointer to the root
    // node of the Trie
    Trie* temp = root;
  
    // Traverse through all the
    // characters of current word
    for (char ch : word) {
  
        // Make a Trie Node, if not
        // already present
        if (temp->arr[ch - 'a'] == NULL) {
            Trie* t = new Trie();
            temp->arr[ch - 'a'] = t;
        }
  
        temp = temp->arr[ch - 'a'];
        temp->idx = i;
    }
}
  
// Function to search the words in Trie
int search(string word)
{
    Trie* temp = root;
  
    // Traverse through all the
    // characters of current word
    for (char ch : word) {
  
        // If no valid Trie Node exists
        // for the current character
        // then there is no match
        if (temp->arr[ch - 'a'] == NULL)
            return -1;
        temp = temp->arr[ch - 'a'];
    }
  
    // Return the resultant index
    return temp->idx;
}
  
// Function to search for a word in
// the dictionary with the given
// prefix and suffix for each query
void findMatchingString(
    string words[], int n,
    vector<vector<string> > Q)
{
    string temp, t;
  
    // Insertion in the Trie
    for (int i = 0; i < n; i++) {
  
        // Form all the words of the
        // form suffix{word and insert
        // them in the trie
        temp = "{" + words[i];
  
        for (int j = words[i].size() - 1;
             j >= 0; j--) {
            t = words[i][j] + temp;
            temp = t;
  
            // Insert into Trie
            insert(t, i);
        }
    }
  
    // Traverse all the queries
    for (int i = 0; i < Q.size(); i++) {
  
        string prefix = Q[i][0];
        string suffix = Q[i][1];
        string temp = suffix + "{" + prefix;
  
        // Stores the index of
        // the required word
        int res;
  
        // Store the index of the
        // word in the dictionary
        res = search(temp);
  
        // In case of match, print
        // the corresponding string
        if (res != -1) {
            cout << words[res] << '\n';
        }
  
        // Otherwise, No match found
        else
            cout << "-1\n";
    }
}
  
// Driver Code
int main()
{
    string arr[]
        = { "apple", "app", "biscuit",
            "mouse", "orange", "bat",
            "microphone", "mine" };
    int N = 8;
    vector<vector<string> > Q = { { "a", "e" }, { "mi", "ne" } };
    findMatchingString(arr, N, Q);
  
    return 0;
}
Output:
apple
mine

Time Complexity: O(N*M2 + Q*M), where M is the maximum length of among all the strings
Auxiliary Space: O(N*M2)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :