Open In App

Longest Common Prefix using Trie

Given a set of strings, find the longest common prefix.

Input  : {“geeksforgeeks”, “geeks”, “geek”, “geezer”}
Output : "gee"

Input  : {"apple", "ape", "april"}
Output : "ap"

Previous Approaches : Word by Word Matching , Character by Character Matching, Divide and Conquer , Binary Search. In this article, an approach using Trie date structure is discussed. Steps:



Algorithm Illustration considering strings as – “geeksforgeeks”, “geeks”, “geek”, “geezer”




// A Program to find the longest common
// prefix of the given words
 
#include<bits/stdc++.h>
using namespace std;
 
// Alphabet size (# of symbols)
#define ALPHABET_SIZE (26)
 
// Converts key current character into index
// use only 'a' through 'z' and lower case
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
 
// Trie node
struct TrieNode
{
    struct TrieNode *children[ALPHABET_SIZE];
 
    // isLeaf is true if the node represents
    // end of a word
    bool isLeaf;
};
 
// Returns new trie node (initialized to NULLs)
struct TrieNode *getNode(void)
{
    struct TrieNode *pNode = new TrieNode;
 
    if (pNode)
    {
        int i;
 
        pNode->isLeaf = false;
 
        for (i = 0; i < ALPHABET_SIZE; i++)
            pNode->children[i] = NULL;
    }
 
    return pNode;
}
 
// If not present, inserts the key into the trie
// If the key is a prefix of trie node, just marks leaf node
void insert(struct TrieNode *root, string key)
{
    int length = key.length();
    int index;
 
    struct TrieNode *pCrawl = root;
 
    for (int level = 0; level < length; level++)
    {
        index = CHAR_TO_INDEX(key[level]);
        if (!pCrawl->children[index])
            pCrawl->children[index] = getNode();
 
        pCrawl = pCrawl->children[index];
    }
 
    // mark last node as leaf
    pCrawl->isLeaf = true;
}
 
// Counts and returns the number of children of the
// current node
int countChildren(struct TrieNode *node, int *index)
{
    int count = 0;
    for (int i=0; i<ALPHABET_SIZE; i++)
    {
        if (node->children[i] != NULL)
        {
            count++;
            *index = i;
        }
    }
    return (count);
}
 
// Perform a walk on the trie and return the
// longest common prefix string
string walkTrie(struct TrieNode *root)
{
    struct TrieNode *pCrawl = root;
    int index;
    string prefix;
 
    while (countChildren(pCrawl, &index) == 1 &&
            pCrawl->isLeaf == false)
    {
        pCrawl = pCrawl->children[index];
        prefix.push_back('a'+index);
    }
    return (prefix);
}
 
// A Function to construct trie
void constructTrie(string arr[], int n, struct TrieNode *root)
{
    for (int i = 0; i < n; i++)
        insert (root, arr[i]);
    return;
}
 
// A Function that returns the longest common prefix
// from the array of strings
string commonPrefix(string arr[], int n)
{
    struct TrieNode *root = getNode();
    constructTrie(arr, n, root);
 
    // Perform a walk on the trie
    return walkTrie(root);
}
 
// Driver program to test above function
int main()
{
    string arr[] = {"geeksforgeeks", "geeks",
                    "geek", "geezer"};
    int n = sizeof (arr) / sizeof (arr[0]);
 
    string ans = commonPrefix(arr, n);
 
    if (ans.length())
        cout << "The longest common prefix is "
             << ans;
    else
        cout << "There is no common prefix";
    return (0);
}




// Java Program to find the longest common
// prefix of the given words
public class Longest_common_prefix {
     
    // Alphabet size (# of symbols)
    static final int ALPHABET_SIZE = 26;
      
    // Trie node
    static class TrieNode
    {
        TrieNode[] children = new TrieNode[ALPHABET_SIZE];
      
        // isLeaf is true if the node represents
        // end of a word
        boolean isLeaf;
         
        // constructor
        public TrieNode() {
            isLeaf = false;
            for (int i = 0; i < ALPHABET_SIZE; i++)
                children[i] = null;
        }
    };
      
    static TrieNode root;
    static int indexs;
      
    // If not present, inserts the key into the trie
    // If the key is a prefix of trie node, just marks
    // leaf node
    static void insert(String key)
    {
        int length = key.length();
        int index;
      
        TrieNode pCrawl = root;
      
        for (int level = 0; level < length; level++)
        {
            index = key.charAt(level) - 'a';
            if (pCrawl.children[index] == null)
                pCrawl.children[index] = new TrieNode();
      
            pCrawl = pCrawl.children[index];
        }
      
        // mark last node as leaf
        pCrawl.isLeaf = true;
    }
      
    // Counts and returns the number of children of the
    // current node
    static int countChildren(TrieNode node)
    {
        int count = 0;
        for (int i=0; i<ALPHABET_SIZE; i++)
        {
            if (node.children[i] != null)
            {
                count++;
                indexs = i;
            }
        }
        return (count);
    }
      
    // Perform a walk on the trie and return the
    // longest common prefix string
    static String walkTrie()
    {
        TrieNode pCrawl = root;
        indexs = 0;
        String prefix = "";
      
        while (countChildren(pCrawl) == 1 &&
                pCrawl.isLeaf == false)
        {
            pCrawl = pCrawl.children[indexs];
            prefix += (char)('a' + indexs);
        }
        return prefix;
    }
      
    // A Function to construct trie
    static void constructTrie(String arr[], int n)
    {
        for (int i = 0; i < n; i++)
            insert (arr[i]);
        return;
    }
      
    // A Function that returns the longest common prefix
    // from the array of strings
    static String commonPrefix(String arr[], int n)
    {
        root = new TrieNode();
        constructTrie(arr, n);
      
        // Perform a walk on the trie
        return walkTrie();
    }
      
    // Driver program to test above function
    public static void main(String args[])
    {
        String arr[] = {"geeksforgeeks", "geeks",
                        "geek", "geezer"};
        int n = arr.length;
      
        String ans = commonPrefix(arr, n);
      
        if (ans.length() != 0)
            System.out.println("The longest common prefix is "+ans);
        else
            System.out.println("There is no common prefix");
    }
}
// This code is contributed by Sumit Ghosh




# Python 3 program to find the longest common prefix
ALPHABET_SIZE = 26
indexs = 0
class TrieNode:
    # constructor
    def __init__(self):
        self.isLeaf = False
        self.children = [None]*ALPHABET_SIZE
 
# Function to facilitate insertion in Trie
# If not present, insert the node in the Trie
def insert(key, root):
    pCrawl = root
    for level in range(len(key)):
        index = ord(key[level]) - ord('a')
        if pCrawl.children[index] == None:
            pCrawl.children[index] = TrieNode()
        pCrawl = pCrawl.children[index]
    pCrawl.isLeaf = True
 
# Function to construct Trie
def constructTrie(arr, n, root):
    for i in range(n):
        insert(arr[i], root)
 
# Counts and returns number of children of the node
def countChildren(node):
    count = 0
    for i in range(ALPHABET_SIZE):
        if node.children[i] != None:
            count +=1
            # Keeping track of diversion in the trie
            global indexs
            indexs = i
    return count
     
# Perform walk on trie and return longest common prefix
def walkTrie(root):
    pCrawl = root
    prefix = ""
    while(countChildren(pCrawl) == 1 and pCrawl.isLeaf == False):
        pCrawl = pCrawl.children[indexs]
        prefix += chr(97 + indexs)
    return prefix or -1
 
# Function that returns longest common prefix
def commonPrefix(arr, n, root):
    constructTrie(arr, n, root)
    return walkTrie(root)
 
# Driver code to test the code
n = 4
arr = ["geeksforgeeks", "geeks", "geek", "geezer"]
root = TrieNode()
print(commonPrefix(arr,n, root))
 
# This code is Contributed by Akshay Jain (DA-IICT)




// C# Program to find the longest common
// prefix of the given words
using System;
     
public class Longest_common_prefix
{
     
    // Alphabet size (# of symbols)
    static readonly int ALPHABET_SIZE = 26;
     
    // Trie node
    public class TrieNode
    {
        public TrieNode[] children = new TrieNode[ALPHABET_SIZE];
     
        // isLeaf is true if the node represents
        // end of a word
        public bool isLeaf;
         
        // constructor
        public TrieNode()
        {
            isLeaf = false;
            for (int i = 0; i < ALPHABET_SIZE; i++)
                children[i] = null;
        }
    };
     
    static TrieNode root;
    static int indexs;
     
    // If not present, inserts the key into the trie
    // If the key is a prefix of trie node, just marks
    // leaf node
    static void insert(String key)
    {
        int length = key.Length;
        int index;
     
        TrieNode pCrawl = root;
     
        for (int level = 0; level < length; level++)
        {
            index = key[level] - 'a';
            if (pCrawl.children[index] == null)
                pCrawl.children[index] = new TrieNode();
     
            pCrawl = pCrawl.children[index];
        }
     
        // mark last node as leaf
        pCrawl.isLeaf = true;
    }
     
    // Counts and returns the number of children of the
    // current node
    static int countChildren(TrieNode node)
    {
        int count = 0;
        for (int i = 0; i < ALPHABET_SIZE; i++)
        {
            if (node.children[i] != null)
            {
                count++;
                indexs = i;
            }
        }
        return (count);
    }
     
    // Perform a walk on the trie and return the
    // longest common prefix string
    static String walkTrie()
    {
        TrieNode pCrawl = root;
        indexs = 0;
        String prefix = "";
     
        while (countChildren(pCrawl) == 1 &&
                pCrawl.isLeaf == false)
        {
            pCrawl = pCrawl.children[indexs];
            prefix += (char)('a' + indexs);
        }
        return prefix;
    }
     
    // A Function to construct trie
    static void constructTrie(String []arr, int n)
    {
        for (int i = 0; i < n; i++)
            insert (arr[i]);
        return;
    }
     
    // A Function that returns the longest common prefix
    // from the array of strings
    static String commonPrefix(String []arr, int n)
    {
        root = new TrieNode();
        constructTrie(arr, n);
     
        // Perform a walk on the trie
        return walkTrie();
    }
     
    // Driver program to test above function
    public static void Main(String []args)
    {
        String []arr = {"geeksforgeeks", "geeks",
                        "geek", "geezer"};
        int n = arr.Length;
     
        String ans = commonPrefix(arr, n);
     
        if (ans.Length != 0)
            Console.WriteLine("The longest common prefix is "+ans);
        else
            Console.WriteLine("There is no common prefix");
    }
}
 
// This code contributed by Rajput-Ji




<script>
    // Javascript Program to find the longest common
    // prefix of the given words
     
    const ALPHABET_SIZE = 26;
     
    // Converts key current character into index
    // use only 'a' through 'z' and lower case
    const CHAR_TO_INDEX = (c) => c.charCodeAt(0) - 'a'.charCodeAt(0);
     
    // Trie node
    class TrieNode {
      constructor() {
        this.children = Array(ALPHABET_SIZE).fill(null);
        this.isLeaf = false;
      }
    }
     
    // Returns new trie node (initialized to NULLs)
    const getNode = () => new TrieNode();
     
    // If not present, inserts the key into the trie
    // If the key is a prefix of trie node, just marks leaf node
    const insert = (root, key) => {
      let length = key.length;
      let index;
     
      let pCrawl = root;
     
      for (let level = 0; level < length; level++) {
        index = CHAR_TO_INDEX(key[level]);
        if (!pCrawl.children[index]) {
          pCrawl.children[index] = getNode();
        }
     
        pCrawl = pCrawl.children[index];
      }
     
      // mark last node as leaf
      pCrawl.isLeaf = true;
    };
     
    // Counts and returns the number of children of the
    // current node
    const countChildren = (node, index) => {
      let count = 0;
      for (let i = 0; i < ALPHABET_SIZE; i++) {
        if (node.children[i] != null) {
          count++;
          index[0] = i;
        }
      }
      return count;
    };
     
    // Perform a walk on the trie and return the
    // longest common prefix string
    const walkTrie = (root) => {
      let pCrawl = root;
      let index = [];
      let prefix = "";
     
      while (countChildren(pCrawl, index) === 1 && !pCrawl.isLeaf) {
        pCrawl = pCrawl.children[index[0]];
        prefix += String.fromCharCode("a".charCodeAt(0) + index[0]);
      }
      return prefix;
    };
     
    // A Function to construct trie
    function constructTrie(arr, n, root) {
      for (let i = 0; i < n; i++) {
        insert(root, arr[i]);
      }
      return;
    };
     
    // A Function that returns the longest common prefix
    // from the array of strings
    function commonPrefix(arr, n) {
      let root = getNode();
      constructTrie(arr, n, root);
     
      // Perform a walk on the trie
      return walkTrie(root);
    };
     
    // Driver program to test above function
      let arr = ["geeksforgeeks", "geeks", "geek", "geezer"];
      let n = arr.length;
     
      let ans = commonPrefix(arr, n);
     
      if (ans.length) {
        document.write("The longest common prefix is "+ans);
      }
      else
      {
          document.write("There is no common prefix");
      }
         
        // This code is contributed by Aman Kumar.
</script>

Output :



The longest common prefix is gee

Time Complexity : Inserting all the words in the trie takes O(MN) time and performing a walk on the trie takes O(M) time, where-

N = Number of strings
M = Length of the largest string

Auxiliary Space: To store all the strings we need to allocate O(26*M*N) ~ O(MN) space for the Trie.  


Article Tags :