Given array A[] of strings of size N, the task for this problem is to print the Maximum Common prefix of string 'i' with other strings from 1 to N apart from 'i' itself for all given strings from 1 to N. Given strings consists of lowercase English letters.
Examples:
Input: {"abc", "abb", "aac"}
Output: 2 2 1
Explanation:
- Answer for first string is two. since first string has maximum length of common prefix is 2. with one of the all other strings.
- Answer for second string is two. since second string has maximum length of common prefix is 2 with one of the all other strings.
- Answer for third string is one. since third string has maximum length of common prefix is 1 with one of the all other strings.
Input: A2 = {"abracadabra", "bracadabra", "racadabra", "acadabra", "cadabra", "adabra", "dabra", "abra", "bra", "ra", "a"}
Output: 4 3 2 1 0 1 0 4 3 2 1
Naive approach: The basic way to solve the problem is as follows:
The basic way to solve this problem is to iterate all other strings for each strings and maintain maximum count.
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: The above approach can be optimized based on the following idea:
Trie data structure can be used to solve this problem.
Follow the steps below to solve the problem:
- All strings are inserted in TRIE by iterating on each string from A[].
- Iterating on all strings from 1 to N.
- For each string remove that string by calling remove().
- Print a maximum length of string with whom the given string has the maximum common prefix by calling query().
- Insert the same string back again in TRIE by insert().
Below is the implementation for the above approach:
// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
// Structure for Node of Trie
struct Node {
// Links of string trie
Node* links[26];
// Count of similar prefixes
// strings has
int cnt = 0;
};
// Root node initialized
Node* root = new Node();
// Insert function for inserting
// words in trie
void insert(string word)
{
// Initializing node variable
Node* node = root;
// Iterating on given word
for (int i = 0; i < word.size(); i++) {
// If node does not exists
if (node->links[word[i] - 'a'] == NULL) {
// Creating new node
node->links[word[i] - 'a'] = new Node();
}
// Next node
node = node->links[word[i] - 'a'];
// Incrementing counter
node->cnt++;
}
}
// Remove function for removing
// words in trie
void remove(string word)
{
// Initializing node variable
Node* node = root;
// Iterating on given word
for (int i = 0; i < word.size(); i++) {
// Next node
node = node->links[word[i] - 'a'];
// Decrementing the counter
node->cnt--;
}
}
// Finding common prefix in all
// other strings
int query(string word)
{
// Count of answer
int cnt = 0;
// Initialization of node variable
Node* node = root;
// Iterating on given word
for (int i = 0; i < word.size(); i++) {
// If doesn't exist break;
if (node->links[word[i] - 'a'] == NULL)
break;
// Next node
node = node->links[word[i] - 'a'];
// If counter zero break;
if (node->cnt == 0)
break;
// Incrementing the counter
cnt++;
}
// Returning the integer
return cnt;
}
// Function for finding Longest Common
// prefix of all given strings in given
// array
void findLCP(vector<string>& A, int N)
{
// Inserting all strings in Trie
for (int i = 0; i < N; i++)
insert(A[i]);
// Finding answer for ith string
for (int i = 0; i < N; i++) {
// Deleting current string from Trie
remove(A[i]);
// Printing answer for i'th string
cout << query(A[i]) << " ";
// Inserting i'th string again
insert(A[i]);
}
cout << endl;
}
// Driver program to test above functions
int main()
{
vector<string> A1 = { "abc", "abb", "aac" };
int N1 = 3;
// Call for test case 1
findLCP(A1, N1);
vector<string> A2
= { "abracadabra", "bracadabra", "racadabra",
"acadabra", "cadabra", "adabra",
"dabra", "abra", "bra",
"ra", "a" };
int N2 = 11;
// Call for test case 2
findLCP(A2, N2);
return 0;
}
// Java code for the above approach:
import java.util.*;
// Structure for Node of Trie
class Node {
// Links of string trie
Node[] links = new Node[26];
// Count of similar prefixes strings has
int cnt = 0;
}
public class Main {
// Root node initialized
static Node root = new Node();
// Insert function for inserting words in trie
static void insert(String word)
{
// Initializing node variable
Node node = root;
// Iterating on given word
for (int i = 0; i < word.length(); i++) {
// If node does not exists
if (node.links[word.charAt(i) - 'a'] == null) {
// Creating new node
node.links[word.charAt(i) - 'a']
= new Node();
}
// Next node
node = node.links[word.charAt(i) - 'a'];
// Incrementing counter
node.cnt++;
}
}
// Remove function for removing words in trie
static void remove(String word)
{
// Initializing node vaiable
Node node = root;
// Iterating on given word
for (int i = 0; i < word.length(); i++) {
// Next node
node = node.links[word.charAt(i) - 'a'];
// Decrementing the counter
node.cnt--;
}
}
// Finding common prefix in all other strings
static int query(String word)
{
// Count of answer
int cnt = 0;
// Initialization of node variable
Node node = root;
// Iterating on given word
for (int i = 0; i < word.length(); i++) {
// If doesn't exist break;
if (node.links[word.charAt(i) - 'a'] == null)
break;
// Next node
node = node.links[word.charAt(i) - 'a'];
// If counter zero break;
if (node.cnt == 0)
break;
// Incrementing the counter
cnt++;
}
// Returning the integer
return cnt;
}
// Function for finding Longest Common prefix of all
// given strings in given array
static void findLCP(List<String> A, int N)
{
// Inserting all strings in Trie
for (int i = 0; i < N; i++)
insert(A.get(i));
// Finding answer for ith string
for (int i = 0; i < N; i++) {
// Deleting current string from Trie
remove(A.get(i));
// Printing answer for i'th string
System.out.print(query(A.get(i)) + " ");
// Inserting i'th string again
insert(A.get(i));
}
System.out.println();
}
// Driver program to test above functions
public static void main(String[] args)
{
List<String> A1
= Arrays.asList("abc", "abb", "aac");
int N1 = 3;
// Call for test case 1
findLCP(A1, N1);
List<String> A2 = Arrays.asList(
"abracadabra", "bracadabra", "racadabra",
"acadabra", "cadabra", "adabra", "dabra",
"abra", "bra", "ra", "a");
int N2 = 11;
// Call for test case 2
findLCP(A2, N2);
}
}
// This code is contributed by rutikbhosale
# Python3 code for the above approach
class Node:
def __init__(self):
# links of string trie
self.links = [None] * 26
# count of similar prefixes strings has
self.cnt = 0
# root node initialize
root = Node()
# Function for inserting words in trie
def insert(word):
# initialize node
node = root
# iterate on word
for i in range(len(word)):
# if node not exist
if not node.links[ord(word[i]) - ord('a')]:
# creating new node
node.links[ord(word[i]) - ord('a')] = Node()
# next node
node = node.links[ord(word[i]) - ord('a')]
# increase count by 1
node.cnt += 1
# Function for removing words in trie
def remove(word):
# initialize node variable
node = root
# iterate on given word
for i in range(len(word)):
# next node
node = node.links[ord(word[i]) - ord('a')]
# decrease the count by 1
node.cnt -= 1
def query(word):
# initialize count to 0
cnt = 0
# initialize node
node = root
# iterate for word
for i in range(len(word)):
# if it doesn't exist break loop
if not node.links[ord(word[i]) - ord('a')]:
break
# next node
node = node.links[ord(word[i]) - ord('a')]
# if counter zero break
if node.cnt == 0:
break
# increase the count by 1
cnt += 1
# return count
return cnt
# Function for finding Longest Common
# prefix of all given strings for given array
def findLCP(A):
# insert all strings in trie
for word in A:
insert(word)
# find answer for i-th string
for word in A:
# delet current string from trie
remove(word)
# print answer for i-th string
print(query(word), end=" ")
# insert i-th string again
insert(word)
print()
# Drive code
A1 = ["abc", "abb", "aac"]
# Function call for test case 1
findLCP(A1)
A2 = ["abracadabra", "bracadabra", "racadabra",
"acadabra", "cadabra", "adabra",
"dabra", "abra", "bra","ra", "a"]
# Function call for test case 2
findLCP(A2)
# This code is contributed by nikhilsainiofficial546
// C# code for the above approach:
using System;
using System.Collections.Generic;
// Structure for Node of Trie
public class Node
{
// Links of string trie
public Node[] links = new Node[26];
// Count of similar prefixes strings has
public int cnt = 0;
}
public class Program
{
// Root node initialized
static Node root = new Node();
// Insert function for inserting words in trie
static void insert(string word)
{
// Initializing node variable
Node node = root;
// Iterating on given word
for (int i = 0; i < word.Length; i++)
{
// If node does not exist
if (node.links[word[i] - 'a'] == null)
{
// Creating new node
node.links[word[i] - 'a'] = new Node();
}
// Next node
node = node.links[word[i] - 'a'];
// Incrementing counter
node.cnt++;
}
}
// Remove function for removing words in trie
static void remove(string word)
{
// Initializing node vaiable
Node node = root;
// Iterating on given word
for (int i = 0; i < word.Length; i++)
{
// Next node
node = node.links[word[i] - 'a'];
// Decrementing the counter
node.cnt--;
}
}
// Finding common prefix in all other strings
static int query(string word)
{
// Count of answer
int cnt = 0;
// Initialization of node variable
Node node = root;
// Iterating on given word
for (int i = 0; i < word.Length; i++)
{
// If doesn't exist break;
if (node.links[word[i] - 'a'] == null)
break;
// Next node
node = node.links[word[i] - 'a'];
// If counter zero break;
if (node.cnt == 0)
break;
// Incrementing the counter
cnt++;
}
// Returning the integer
return cnt;
}
// Function for finding Longest Common prefix of all
// given strings in given array
static void findLCP(List<string> A, int N)
{
// Inserting all strings in Trie
for (int i = 0; i < N; i++)
insert(A[i]);
// Finding answer for ith string
for (int i = 0; i < N; i++)
{
// Deleting current string from Trie
remove(A[i]);
// Printing answer for i'th string
Console.Write(query(A[i]) + " ");
// Inserting i'th string again
insert(A[i]);
}
Console.WriteLine();
}
// Driver program to test above functions
public static void Main()
{
List<string> A1 = new List<string> { "abc", "abb", "aac" };
int N1 = 3;
// Call for test case 1
findLCP(A1, N1);
List<string> A2 = new List<string> {
"abracadabra", "bracadabra", "racadabra",
"acadabra", "cadabra", "adabra", "dabra",
"abra", "bra", "ra", "a"
};
int N2 = 11;
// Call for test case 2
findLCP(A2, N2);
}
}
// This code is contributed by Pushpesh Raj.
// JavaScript code for the above approach:
// Structure for Node of Trie
class Node {
// Links of string trie
constructor() {
this.links = Array(26).fill(null);
// Count of similar prefixes
// strings has
this.cnt = 0;
}
}
// Root node initialized
const root = new Node();
// Insert function for inserting
// words in trie
function insert(word) {
// Initializing node variable
let node = root;
// Iterating on given word
for (let i = 0; i < word.length; i++) {
// If node does not exists
if (node.links[word.charCodeAt(i) - 97] === null) {
// Creating new node
node.links[word.charCodeAt(i) - 97] = new Node();
}
// Next node
node = node.links[word.charCodeAt(i) - 97];
// Incrementing counter
node.cnt++;
}
}
// Remove function for removing
// words in trie
function remove(word) {
// Initializing node variable
let node = root;
// Iterating on given word
for (let i = 0; i < word.length; i++) {
// Next node
node = node.links[word.charCodeAt(i) - 97];
// Decrementing the counter
node.cnt--;
}
}
// Finding common prefix in all
// other strings
function query(word) {
// Count of answer
let cnt = 0;
// Initialization of node variable
let node = root;
// Iterating on given word
for (let i = 0; i < word.length; i++) {
// If doesn't exist break;
if (node.links[word.charCodeAt(i) - 97] === null)
break;
// Next node
node = node.links[word.charCodeAt(i) - 97];
// If counter zero break;
if (node.cnt === 0)
break;
// Incrementing the counter
cnt++;
}
// Returning the integer
return cnt;
}
// Function for finding Longest Common
// prefix of all given strings in given
// array
function findLCP(A, N) {
// Inserting all strings in Trie
for (let i = 0; i < N; i++)
insert(A[i]);
// Finding answer for ith string
for (let i = 0; i < N; i++) {
// Deleting current string from Trie
remove(A[i]);
// Printing answer for i'th string
console.log(query(A[i]) + " ");
// Inserting i'th string again
insert(A[i]);
}
console.log("");
}
// Driver program to test above functions
const A1 = ["abc", "abb", "aac"];
const N1 = 3;
// Call for test case 1
findLCP(A1, N1);
const A2 = ["abracadabra", "bracadabra", "racadabra", "acadabra",
"cadabra", "adabra", "dabra", "abra", "bra", "ra", "a", ];
const N2 = 11;
// Call for test case 2
findLCP(A2, N2);
Output
2 2 1 4 3 2 1 0 1 0 4 3 2 1
Time Complexity: O(N*K2), where N is the number of strings and K is the maximum length of the strings.
Auxiliary Space: O(N*K)
Related Articles: