Open In App

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

Last Updated : 11 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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”.

C++




#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    // N is the number of strings in the array
    int N=8;
     
    // Declare an array of size N
    string arr[]
        = { "apple", "app", "biscuit",
            "mouse", "orange", "bat",
            "mine", "mine" };
     
    vector<vector<string> > Q = { { "a", "e" }, { "mi", "ne" } };
     
    // Taking input the queries
    string prefix, suffix;
    for(int i=0; i<Q.size(); i++)
    {
        prefix = Q[i][0];
        suffix = Q[i][1];
         
        // Flag to check if string is found
        // with given prefix and suffix
        int found = 0;
         
        // Check every string in arr[]
        for(int j=0; j<N; j++)
        {
            // If string is found with given
            // prefix and suffix
            if(arr[j].find(prefix) == 0 && arr[j].rfind(suffix) == arr[j].length()-suffix.length())
            {
                // Print the string
                cout<<arr[j]<<endl;
                 
                // Set flag to 1 to indicate that
                // string is found
                found = 1;
                break;
            }
        }
        if(found == 0)
            cout<<"-1"<<endl;
    }
    return 0;
}


Java




// Java code for above approach
import java.util.*;
 
public class Main {
  public static void main(String[] args) {
    // N is the number of strings in the array
    int N = 8;
 
    // Declare an array of size N
    String[] arr = {"apple", "app", "biscuit", "mouse", "orange", "bat", "mine", "mine"};
 
    List<List<String>> Q = new ArrayList<>();
    Q.add(Arrays.asList("a", "e"));
    Q.add(Arrays.asList("mi", "ne"));
 
    // Taking input the queries
    String prefix, suffix;
    for (int i = 0; i < Q.size(); i++) {
      prefix = Q.get(i).get(0);
      suffix = Q.get(i).get(1);
 
      // Flag to check if string is found
      // with given prefix and suffix
      int found = 0;
 
      // Check every string in arr[]
      for (int j = 0; j < N; j++) {
        // If string is found with given
        // prefix and suffix
        if (arr[j].indexOf(prefix) == 0 && arr[j].lastIndexOf(suffix) == arr[j].length() - suffix.length()) {
          // Print the string
          System.out.println(arr[j]);
 
          // Set flag to 1 to indicate that
          // string is found
          found = 1;
          break;
        }
      }
      if (found == 0)
        System.out.println("-1");
    }
  }
}
 
// This code is contributed by Utkarsh Kumar.


Python3




# Python program for the above approach
 
# N is the number of strings in the array
N = 8
 
# Declare an array of size N
arr = ["apple", "app", "biscuit", "mouse", "orange", "bat", "mine", "mine"]
Q = [["a", "e"], ["mi", "ne"]]
 
for i in range(len(Q)):
   
  # Taking input the queries
    prefix = Q[i][0]
    suffix = Q[i][1]
     
    # Flag to check if string is found
    # with given prefix and suffix
    found = 0
     
    # Check every string in arr[]
    for j in range(N):
       
      # If string is found with given
      # prefix and suffix
        if arr[j].find(prefix) == 0 and arr[j].rfind(suffix) == len(arr[j]) - len(suffix):
             
            # Print the string
            print(arr[j])
             
           # Set flag to 1 to indicate that
          # string is found
            found = 1
            break
     
    if found == 0:
        print("-1")
 
 
# This code is contributed by rishabmalhdjio


C#




// C# Program for the above approach
using System;
using System.Collections.Generic;
 
class Program
{
    static void Main(string[] args)
    {
        // N is the number of strings in the array
        int N = 8;
 
        // Declare an array of size N
        string[] arr = { "apple", "app", "biscuit", "mouse", "orange", "bat", "mine", "mine" };
 
        List<List<string>> Q = new List<List<string>> { new List<string> { "a", "e" }, new List<string> { "mi", "ne" } };
 
        // Taking input the queries
        string prefix, suffix;
        for (int i = 0; i < Q.Count; i++)
        {
            prefix = Q[i][0];
            suffix = Q[i][1];
 
            // Flag to check if string is found
            // with given prefix and suffix
            int found = 0;
 
            // Check every string in arr[]
            for (int j = 0; j < N; j++)
            {
                // If string is found with given
                // prefix and suffix
                if (arr[j].IndexOf(prefix) == 0 && arr[j].LastIndexOf(suffix) == arr[j].Length - suffix.Length)
                {
                    // Print the string
                    Console.WriteLine(arr[j]);
 
                    // Set flag to 1 to indicate that
                    // string is found
                    found = 1;
                    break;
                }
            }
            if (found == 0)
                Console.WriteLine("-1");
        }
    }
}
 
// Contributed by rishabmalhdijo


Javascript




// N is the number of strings in the array
const N = 8;
 
// Declare an array of size N
const arr = ["apple", "app", "biscuit", "mouse", "orange", "bat", "mine", "mine"];
 
const Q = [["a", "e"], ["mi", "ne"]];
 
// Taking input the queries
let prefix, suffix;
for (let i = 0; i < Q.length; i++) {
  prefix = Q[i][0];
  suffix = Q[i][1];
 
  // Flag to check if string is found
  // with given prefix and suffix
  let found = 0;
 
  // Check every string in arr[]
  for (let j = 0; j < N; j++) {
    // If string is found with given
    // prefix and suffix
    if (arr[j].startsWith(prefix) && arr[j].endsWith(suffix)) {
      // Print the string
      console.log(arr[j]);
 
      // Set flag to 1 to indicate that
      // string is found
      found = 1;
      break;
    }
  }
  if (found == 0) console.log("-1");
}


Output

apple
mine

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


Java




// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
  // Trie Node
  public static class Trie {
 
    Trie []arr = new Trie[27];
 
    // Stores the index of the word
    // in the dictionary
    int idx;
  };
 
  // Root node of the Trie
  public static Trie root;
 
  // Function to insert the words in
  // the Trie
  public static 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 (int ch=0; ch < word.length(); ch++){
 
      // Make a Trie Node, if not
      // already present
      if (temp.arr[word.charAt(ch) - 'a'] == null) {
        Trie t = new Trie();
        temp.arr[word.charAt(ch) - 'a'] = t;
      }
 
      temp = temp.arr[word.charAt(ch) - 'a'];
      temp.idx = i;
    }
  }
 
  // Function to search the words in Trie
  public static int search(String word)
  {
    Trie temp = root;
 
    // Traverse through all the
    // characters of current word
    for (int ch=0; ch < word.length(); ch++) {
 
      // If no valid Trie Node exists
      // for the current character
      // then there is no match
      if (temp.arr[word.charAt(ch) - 'a'] == null)
        return -1;
      temp = temp.arr[word.charAt(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
  public static void findMatchingString(
    String[] words, int n,
    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].length() - 1;
           j >= 0; j--) {
        t = words[i].charAt(j) + temp;
        temp = t;
 
        // Insert into Trie
        insert(t, i);
      }
    }
 
    // Traverse all the queries
    for (int i = 0; i < Q.length ; i++) {
 
      String prefix = Q[i][0];
      String suffix = Q[i][1];
      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) {
        System.out.println(words[res]);
      }
 
      // Otherwise, No match found
      else
        System.out.println("-1");
    }
  }
 
  public static void main (String[] args) {
    String[] arr
      = { "apple", "app", "biscuit",
         "mouse", "orange", "bat",
         "microphone", "mine" };
    int N = 8;
    root=new Trie();
    String[][] Q = { { "a", "e" }, { "mi", "ne" } };
    findMatchingString(arr, N, Q);
  }
}
 
// This code is contributed by Aman Kumar.


Python3




# Trie Node
class TrieNode:
    def __init__(self):
        self.arr = [None] * 27
        self.idx = None
 
# Root node of the Trie
root = TrieNode()
 
# Function to insert the words in
# the Trie
def insert(word, i):
    # Temporary pointer to the root
    # node of the Trie
    temp = root
 
    # Traverse through all the
    # characters of current word
    for ch in word:
        # Make a Trie Node, if not
        # already present
        if temp.arr[ord(ch) - ord('a')] is None:
            t = TrieNode()
            temp.arr[ord(ch) - ord('a')] = t
        temp = temp.arr[ord(ch) - ord('a')]
        temp.idx = i
 
# Function to search the words in Trie
def search(word):
    temp = root
 
    # Traverse through all the
    # characters of current word
    for ch in word:
        # If no valid Trie Node exists
        # for the current character
        # then there is no match
        if temp.arr[ord(ch) - ord('a')] is None:
            return -1
        temp = temp.arr[ord(ch) - ord('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
def findMatchingString(words, Q):
    # Insertion in the Trie
    for i in range(len(words)):
        # Form all the words of the
        # form suffix{word and insert
        # them in the trie
        temp = "{" + words[i]
        for j in range(len(words[i]) - 1, -1, -1):
            t = words[i][j] + temp
            temp = t
            # Insert into Trie
            insert(t, i)
 
    # Traverse all the queries
    for i in range(len(Q)):
        prefix = Q[i][0]
        suffix = Q[i][1]
        temp = suffix + "{" + prefix
 
        # Stores the index of
        # the required word
        res = search(temp)
 
        # In case of match, print
        # the corresponding string
        if res != -1:
            print(words[res])
        # Otherwise, No match found
        else:
            print("-1")
 
# Driver Code
if __name__ == "__main__":
    words = ["apple", "app", "biscuit", "mouse", "orange", "bat", "microphone", "mine"]
    Q = [['a', 'e'], ['mi', 'ne']]
    findMatchingString(words, Q)


C#




// C# program for the above approach
using System;
class GFG {
 
  // Trie Node
  public class Trie {
    public Trie[] arr = new Trie[27];
 
    // Stores the index of the word
    // in the dictionary
    public int idx;
  };
 
  // Root node of the Trie
  public static Trie root;
 
  // Function to insert the words in
  // the Trie
  public static 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 (int ch = 0; ch < word.Length; ch++) {
 
      // Make a Trie Node, if not
      // already present
      if (temp.arr[word[ch] - 'a'] == null) {
        Trie t = new Trie();
        temp.arr[word[ch] - 'a'] = t;
      }
 
      temp = temp.arr[word[ch] - 'a'];
      temp.idx = i;
    }
  }
 
  // Function to search the words in Trie
  public static int search(String word)
  {
    Trie temp = root;
 
    // Traverse through all the
    // characters of current word
    for (int ch = 0; ch < word.Length; ch++) {
 
      // If no valid Trie Node exists
      // for the current character
      // then there is no match
      if (temp.arr[word[ch] - 'a'] == null)
        return -1;
      temp = temp.arr[word[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
  public static void
    findMatchingString(String[] words, int n, 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].Length - 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.Length; i++) {
      String prefix = Q[i][0];
      String suffix = Q[i][1];
      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) {
        Console.WriteLine(words[res]);
      }
 
      // Otherwise, No match found
      else
        Console.WriteLine("-1");
    }
  }
 
  public static void Main(String[] args)
  {
    String[] arr
      = { "apple""app", "biscuit",    "mouse",
         "orange", "bat", "microphone", "mine" };
    int N = 8;
    root = new Trie();
    String[][] Q = { new String[] { "a", "e" },
                    new String[] { "mi", "ne" } };
    findMatchingString(arr, N, Q);
  }
}
 
// This code is contributed by ishankhandelwals.


Javascript




// Javascript program for the above approach
 
// Trie Node
class Trie {
  constructor() {
    this.arr = new Array(27).fill(null);
    this.idx = null;
  }
}
 
// Root node of the Trie
let root = new Trie();
 
// Function to insert the words in
// the Trie
function insert(word, i) {
  // Temporary pointer to the root
  // node of the Trie
  let temp = root;
 
  // Traverse through all the
  // characters of current word
  for (let ch of word) {
    // Make a Trie Node, if not
    // already present
    if (temp.arr[ch.charCodeAt(0) - 97] == null) {
      temp.arr[ch.charCodeAt(0) - 97] = new Trie();
    }
 
    temp = temp.arr[ch.charCodeAt(0) - 97];
    temp.idx = i;
  }
}
 
// Function to search the words in Trie
function search(word) {
  let temp = root;
 
  // Traverse through all the
  // characters of current word
  for (let ch of word) {
    // If no valid Trie Node exists
    // for the current character
    // then there is no match
    if (temp.arr[ch.charCodeAt(0) - 97] == null) return -1;
    temp = temp.arr[ch.charCodeAt(0) - 97];
  }
 
  // 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
function findMatchingString(words, n, Q) {
  let temp, t;
 
  // Insertion in the Trie
  for (let i = 0; i < n; i++) {
    // Form all the words of the
    // form suffix{word and insert
    // them in the trie
    temp = "{" + words[i];
 
    for (let j = words[i].length - 1; j >= 0; j--) {
      t = words[i][j] + temp;
      temp = t;
 
      // Insert into Trie
      insert(t, i);
    }
  }
 
  // Traverse all the queries
  for (let i = 0; i < Q.length; i++) {
    let prefix = Q[i][0];
    let suffix = Q[i][1];
    let temp = suffix + "{" + prefix;
 
    // Stores the index of
    // the required word
    let res;
 
    // Store the index of the
    // word in the dictionary
    res = search(temp);
 
    // In case of match, print
    // the corresponding string
    if (res != -1) {
      console.log(words[res]);
    }
 
    // Otherwise, No match found
    else console.log(-1);
  }
}
 
// Driver Code
let arr = ["apple", "app", "biscuit", "mouse", "orange", "bat", "microphone", "mine"];
let N = 8;
let Q = [["a", "e"], ["mi", "ne"]];
findMatchingString(arr, N, Q);
 
// This code is contributed by ishankhandelwals.


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)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads