Open In App

Maximum number of Strings with Common Prefix of length K

Last Updated : 21 Feb, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string array arr[] of length N, the task is to find the maximum number of strings that share a common prefix of length K.

Examples:

Input: arr = { { "hello", "heydeei", "hap", "hak", "paloa", "padfk", "padfla", "pada" } }, K = 4
Output: 2
Explanation: String padfk", "padfla" are the two string that share the common prefix of length k.

Input: arr = { { "happy", "hapi", "hape", "hak", "paloa", "padfk", "padfla", "pada" } }, K = 3
Output: 3

An approach using Trie:

The idea is to use Trie data structure to keep a count of all occurrences of a prefix by maintaining a variable count in the structure of the node of Trie. While inserting a new string into trie keep checking K character of new strings are inserted or not. If we'd already inserted K characters into trie than maximise the count of prefix at that node.

Follow the steps below to implement the above idea:

  • Iterate over the given string array and Insert the given strings into Trie one by one
    • Initialize a trie node curr which points to the root initially
    • Iterate over the length of the given string
      • Check if the node for the current character exists in trie
        • If not exist then create a new trie node and assign the reference to the current node child
      • Increment the count of prefixes.
      • Check if the length of the current string becomes greater than the required K.
        • If true, then update the result with the maximum between the current result or the count of occurrences of the current prefix.
      • Move the current pointer to the next node

Below is the implementation of the above approach.

C++
// C++ code to implement the approach

#include <bits/stdc++.h>
using namespace std;

// Structure of a Trie Node
struct Node {
    Node* child[26];
    int count = 0;
};

Node* root;

int result = 0, K;

// Insert given string into Trie
void insert(string& s)
{

    // Initialize a Trie Node curr which
    // point to root initially
    Node* curr = root;

    // Iterate over the length of
    // given string
    for (int i = 0; i < s.size(); i++) {

        // Check if Node for current
        // character exit in Trie If not
        // exist then create new Trie node
        // and assign the reference to
        // current node child
        if (curr->child[s[i] - 'a'] == NULL) {
            curr->child[s[i] - 'a'] = new Node();
        }

        // Increment the count of prefix.
        curr->child[s[i] - 'a']->count++;

        // Check if length of the current
        // string becomes greater than
        // required k If true, then maximise
        // longest prefix will result
        if (i + 1 == K) {
            result = max(result,
                         curr->child[s[i] - 'a']->count);
            break;
        }

        // Move the current pointer
        // to next node
        curr = curr->child[s[i] - 'a'];
    }
}

// Driver code
int main()
{

    vector<string> arr
        = { { "hello", "heydeei", "hap", "hak", "paloa",
              "padfk", "padfla", "pada" } };
    K = 4;

    // Initialize root of Trie Node
    root = new Node();
    for (auto s : arr) {
        insert(s);
    }

    cout << result;
    return 0;
}
Java
// Java program to implement
// the above approach
import java.util.*;

class GFG
{

  // Structure of a Trie Node
  public static class Node {
    Node []child = new Node[26];
    int count = 0;
  };

  public static Node root;

  public static int result = 0, K;

  // Insert given string into Trie
  public static void insert(String s)
  {

    // Initialize a Trie Node curr which
    // point to root initially
    Node curr= root;

    // Iterate over the length of
    // given string
    for (int i = 0; i < s.length(); i++) {

      // Check if Node for current
      // character exit in Trie If not
      // exist then create new Trie node
      // and assign the reference to
      // current node child
      if (curr.child[s.charAt(i) - 'a'] == null) {
        curr.child[s.charAt(i) - 'a'] = new Node();
      }

      // Increment the count of prefix.
      curr.child[s.charAt(i) - 'a'].count++;

      // Check if length of the current
      // string becomes greater than
      // required k If true, then maximise
      // longest prefix will result
      if (i + 1 == K) {
        result = Math.max(result,curr.child[s.charAt(i) - 'a'].count);
        break;
      }

      // Move the current pointer
      // to next node
      curr = curr.child[s.charAt(i) - 'a'];
    }
  }

  // Driver code
  public static void main(String[] args)
  {

    String[] arr = { "hello", "heydeei", "hap", "hak", "paloa",
                    "padfk", "padfla", "pada" } ;
    K = 4;

    // Initialize root of Trie Node
    root = new Node();
    for (String s : arr) {
      insert(s);
    }

    System.out.print(result);
  }
}

// This code is contributed by Pushpesh Raj.
Python3
# Python3 code to implement the approach

# Structure of a Trie Node
class Node:
    
    # Stores index
    # of string
    def __init__(self):
        self.child = [None]*26
        self.count = 0
    
result=0
K=0
root = None

# Insert given string into Trie
def insert(s):
    global root
    global result
    global K
    
    # Initialize a Trie Node curr which
    # point to root initially
    
    curr = root

    # Iterate over the length of
    # given string
    for i in range(len(s)):

        # Check if Node for current
        # character exit in Trie If not
        # exist then create new Trie node
        # and assign the reference to
        # current node child
        if (not curr.child[ord(s[i]) - ord('a')]):

            # Create a new node of Trie.
            curr.child[ord(s[i]) - ord('a')] = Node()
        
        # Increment the count of prefix.
        curr.child[ord(s[i]) - ord('a')].count += 1
        
        # Check if length of the current
        # string becomes greater than
        # required k If true, then maximise
        # longest prefix will result
        if(i+1==K):
            result=max(result,curr.child[ord(s[i]) - ord('a')].count)
            break

        # Move the current pointer
        # to next node
        curr = curr.child[ord(s[i]) - ord('a')]
        
    return curr



# Driver Code
if __name__ == '__main__':
    arr = ["hello", "heydeei", "hap", "hak", "paloa","padfk", "padfla", "pada"]
    K=4

    N = len(arr)
    root=Node()
    
    for i in range(N):
        insert(arr[i])

    print(result)

# This code is contributed by Aman Kumar
C#
// C# program to implement
// the above approach
using System;
public class GFG {

  // Structure of a Trie Node
  class Node {
    public Node[] child = new Node[26];
    public int count = 0;
  };

  static Node root;

  static int result = 0, K;

  // Insert given string into Trie
  static void insert(String s)
  {

    // Initialize a Trie Node curr which
    // point to root initially
    Node curr = root;

    // Iterate over the length of
    // given string
    for (int i = 0; i < s.Length; i++) {

      // Check if Node for current
      // character exit in Trie If not
      // exist then create new Trie node
      // and assign the reference to
      // current node child
      if (curr.child[s[i] - 'a'] == null) {
        curr.child[s[i] - 'a'] = new Node();
      }

      // Increment the count of prefix.
      curr.child[s[i] - 'a'].count++;

      // Check if length of the current
      // string becomes greater than
      // required k If true, then maximise
      // longest prefix will result
      if (i + 1 == K) {
        result = Math.Max(
          result, curr.child[s[i] - 'a'].count);
        break;
      }

      // Move the current pointer
      // to next node
      curr = curr.child[s[i] - 'a'];
    }
  }

  // Driver code
  static void Main()
  {

    string[] arr
      = { "hello", "heydeei", "hap",    "hak",
         "paloa", "padfk",   "padfla", "pada" };
    K = 4;

    // Initialize root of Trie Node
    root = new Node();
    for (int i = 0; i < arr.Length; i++) {
      insert(arr[i]);
    }

    Console.Write(result);
  }
}

// This code is contributed by garg28harsh.
JavaScript
// javascript code to implement the approach

// Structure of a Trie Node
class Node {
    constructor(){
    this.child = new Array(26);
    this.count = 0;
    }
}

let root;

let result = 0, K;

// Insert given string into Trie
function insert( s)
{
    // Initialize a Trie Node curr which
    // point to root initially
    let curr = root;
    // Iterate over the length of
    // given string
    for (let i = 0; i < s.length; i++) {

        // Check if Node for current
        // character exit in Trie If not
        // exist then create new Trie node
        // and assign the reference to
        // current node child
        let x= s.charCodeAt(i)-97;
        if (curr.child[x] == null) {
            curr.child[x] = new Node();
        }

        // Increment the count of prefix.
        curr.child[x].count++;

        // Check if length of the current
        // string becomes greater than
        // required k If true, then maximise
        // longest prefix will result
        if (i + 1 == K) {
            result = Math.max(result,
                         curr.child[x].count);
            break;
        }

        // Move the current pointer
        // to next node
        curr = curr.child[x];
    }
}

// Driver code

    let arr = [ "hello", "heydeei", "hap", "hak", "paloa",
              "padfk", "padfla", "pada"];
    K = 4;

    // Initialize root of Trie Node
    root = new Node();
    for (let i=0;i<arr.length;i++) {
        let s= arr[i];
        insert(s);
    }

    console.log(result);
    
    // This code is contributed by garg28harsh.

Output
2

Time Complexity: O(N * K), where N is the length of the given string array.
Auxiliary Space: O(N * K)


Next Article

Similar Reads