GFG App
Open App
Browser
Continue

# Count of distinct substrings of a string using Suffix Trie

Given a string of length n of lowercase alphabet characters, we need to count total number of distinct substrings of this string. Examples:

Input  : str = “ababa”
Output : 10
Total number of distinct substring are 10, which are,
"", "a", "b", "ab", "ba", "aba", "bab", "abab", "baba"
and "ababa"

The idea is create a Trie of all suffixes of given string. Once the Trie is constricted, our answer is total number of nodes in the constructed Trie. For example below diagram represent Trie of all suffixes for “ababa”. Total number of nodes is 10 which is our answer.

How does this work?

• Each root to node path of a Trie represents a prefix of words present in Trie. Here we words are suffixes. So each node represents a prefix of suffixes.
• Every substring of a string “str” is a prefix of a suffix of “str”.

Below is implementation based on above idea.

## C++

 // A C++ program to find the count of distinct substring // of a string using trie data structure #include #define MAX_CHAR 26 using namespace std;   // A Suffix Trie (A Trie of all suffixes) Node class SuffixTrieNode { public:     SuffixTrieNode *children[MAX_CHAR];     SuffixTrieNode() // Constructor     {         // Initialize all child pointers as NULL         for (int i = 0; i < MAX_CHAR; i++)           children[i] = NULL;     }       // A recursive function to insert a suffix of the s     // in subtree rooted with this node     void insertSuffix(string suffix); };   // A Trie of all suffixes class SuffixTrie {     SuffixTrieNode *root;     int _countNodesInTrie(SuffixTrieNode *); public:     // Constructor (Builds a trie of suffies of the given text)     SuffixTrie(string s)     {         root = new SuffixTrieNode();           // Consider all suffixes of given string and insert         // them into the Suffix Trie using recursive function         // insertSuffix() in SuffixTrieNode class         for (int i = 0; i < s.length(); i++)             root->insertSuffix(s.substr(i));     }       //  method to count total nodes in suffix trie     int countNodesInTrie() { return _countNodesInTrie(root); } };   // A recursive function to insert a suffix of the s in // subtree rooted with this node void SuffixTrieNode::insertSuffix(string s) {     // If string has more characters     if (s.length() > 0)     {         // Find the first character and convert it         // into 0-25 range.         char cIndex = s.at(0) - 'a';           // If there is no edge for this character,         // add a new edge         if (children[cIndex] == NULL)             children[cIndex] = new SuffixTrieNode();           // Recur for next suffix         children[cIndex]->insertSuffix(s.substr(1));     } }   // A recursive function to count nodes in trie int SuffixTrie::_countNodesInTrie(SuffixTrieNode* node) {     // If all characters of pattern have been processed,     if (node == NULL)         return 0;       int count = 0;     for (int i = 0; i < MAX_CHAR; i++)     {         // if children is not NULL then find count         // of all nodes in this subtrie         if (node->children[i] != NULL)             count += _countNodesInTrie(node->children[i]);     }       // return count of nodes of subtrie and plus     // 1 because of node's own count     return (1 + count); }   // Returns count of distinct substrings of str int countDistinctSubstring(string str) {     // Construct a Trie of all suffixes     SuffixTrie sTrie(str);       // Return count of nodes in Trie of Suffixes     return sTrie.countNodesInTrie(); }   // Driver program to test above function int main() {     string str = "ababa";     cout << "Count of distinct substrings is "          << countDistinctSubstring(str);     return 0; }

## Java

 // A Java program to find the count of distinct substring // of a string using trie data structure public class Suffix {     // A Suffix Trie (A Trie of all suffixes) Node     static class SuffixTrieNode     {         static final int MAX_CHAR = 26;         SuffixTrieNode[] children = new SuffixTrieNode[MAX_CHAR];           SuffixTrieNode() // Constructor         {             // Initialize all child pointers as NULL             for (int i = 0; i < MAX_CHAR; i++)                 children[i] = null;         }           // A recursive function to insert a suffix of the s in         // subtree rooted with this node         void insertSuffix(String s)         {             // If string has more characters             if (s.length() > 0)             {                 // Find the first character and convert it                 // into 0-25 range.                 char cIndex = (char) (s.charAt(0) - 'a');                   // If there is no edge for this character,                 // add a new edge                 if (children[cIndex] == null)                     children[cIndex] = new SuffixTrieNode();                   // Recur for next suffix                 children[cIndex].insertSuffix(s.substring(1));                 }         }     }           // A Trie of all suffixes     static class Suffix_trie     {         static final int MAX_CHAR = 26;         SuffixTrieNode root;           // Constructor (Builds a trie of suffies of the given text)         Suffix_trie(String s) {             root = new SuffixTrieNode();               // Consider all suffixes of given string and insert             // them into the Suffix Trie using recursive function             // insertSuffix() in SuffixTrieNode class             for (int i = 0; i < s.length(); i++)                 root.insertSuffix(s.substring(i));         }           // A recursive function to count nodes in trie         int _countNodesInTrie(SuffixTrieNode node)         {             // If all characters of pattern have been processed,             if (node == null)                 return 0;               int count = 0;             for (int i = 0; i < MAX_CHAR; i++) {                   // if children is not NULL then find count                 // of all nodes in this subtrie                 if (node.children[i] != null)                     count += _countNodesInTrie(node.children[i]);             }               // return count of nodes of subtrie and plus             // 1 because of node's own count             return (1 + count);         }           // method to count total nodes in suffix trie         int countNodesInTrie()         {             return _countNodesInTrie(root);         }       }       // Returns count of distinct substrings of str     static int countDistinctSubstring(String str)     {         // Construct a Trie of all suffixes         Suffix_trie sTrie = new Suffix_trie(str);           // Return count of nodes in Trie of Suffixes         return sTrie.countNodesInTrie();     }       // Driver program to test above function     public static void main(String args[])     {         String str = "ababa";         System.out.println("Count of distinct substrings is "                 + countDistinctSubstring(str));               } } // This code is contributed by Sumit Ghosh

## Python3

 # Python program to find the count of distinct substring # of a string using trie data structure   # A Suffix Trie (A Trie of all suffixes) Node class SuffixTrieNode:     def __init__(self):         # Initialize all child pointers as NULL         self.children = [None] * 26           # A recursive function to insert a suffix of the s in     # subtree rooted with this node     def insert_suffix(self, suffix):         # If string has more characters         if suffix:             # Find the first character and convert it             # into 0-25 range.             c_index = ord(suffix[0]) - ord('a')             # If there is no edge for this character,             # add a new edge             if not self.children[c_index]:                 self.children[c_index] = SuffixTrieNode()             # Recur for next suffix             self.children[c_index].insert_suffix(suffix[1:])   # A Trie of all suffixes class SuffixTrie:     def __init__(self, s):         # Constructor (Builds a trie of suffies of the given text)         self.root = SuffixTrieNode()         for i in range(len(s)):             # Consider all suffixes of given string and insert             # them into the Suffix Trie using recursive function             # insertSuffix() in SuffixTrieNode class             self.root.insert_suffix(s[i:])           # method to count total nodes in suffix trie     def countNodesInTrie(self):         return self._countNodesInTrie(self.root)           def _countNodesInTrie(self, node):         # If all characters of pattern have been processed,         if node is None:             return 0         count = 0         for i in range(26):             # if children is not NULL then find count             # of all nodes in this subtrie             if node.children[i]:                 count += self._countNodesInTrie(node.children[i])         # return count of nodes of subtrie and plus         # 1 because of node's own count         return count + 1   # Returns count of distinct substrings of str def countDistinctSubstring(str):     # Construct a Trie of all suffixes     s_trie = SuffixTrie(str)     # Return count of nodes in Trie of Suffixes     return s_trie.countNodesInTrie()   # Driver program to test above function if __name__ == '__main__':     str = "ababa"     print("Count of distinct substrings is", countDistinctSubstring(str))   # This code is contributed by Aman Kumar.

## C#

 // C# program to find the count of distinct substring // of a string using trie data structure using System;   public class Suffix {     // A Suffix Trie (A Trie of all suffixes) Node     public class SuffixTrieNode     {         static readonly int MAX_CHAR = 26;         public SuffixTrieNode[] children = new SuffixTrieNode[MAX_CHAR];           public SuffixTrieNode() // Constructor         {             // Initialize all child pointers as NULL             for (int i = 0; i < MAX_CHAR; i++)                 children[i] = null;         }           // A recursive function to insert a suffix of the s in         // subtree rooted with this node         public void insertSuffix(String s)         {             // If string has more characters             if (s.Length > 0)             {                 // Find the first character and convert it                 // into 0-25 range.                 char cIndex = (char) (s[0] - 'a');                   // If there is no edge for this character,                 // add a new edge                 if (children[cIndex] == null)                     children[cIndex] = new SuffixTrieNode();                   // Recur for next suffix                 children[cIndex].insertSuffix(s.Substring(1));                 }         }     }           // A Trie of all suffixes     public class Suffix_trie     {         static readonly int MAX_CHAR = 26;         public SuffixTrieNode root;           // Constructor (Builds a trie of suffies of the given text)         public Suffix_trie(String s)         {             root = new SuffixTrieNode();               // Consider all suffixes of given string and insert             // them into the Suffix Trie using recursive function             // insertSuffix() in SuffixTrieNode class             for (int i = 0; i < s.Length; i++)                 root.insertSuffix(s.Substring(i));         }           // A recursive function to count nodes in trie         public int _countNodesInTrie(SuffixTrieNode node)         {             // If all characters of pattern have been processed,             if (node == null)                 return 0;               int count = 0;             for (int i = 0; i < MAX_CHAR; i++)             {                   // if children is not NULL then find count                 // of all nodes in this subtrie                 if (node.children[i] != null)                     count += _countNodesInTrie(node.children[i]);             }               // return count of nodes of subtrie and plus             // 1 because of node's own count             return (1 + count);         }           // method to count total nodes in suffix trie         public int countNodesInTrie()         {             return _countNodesInTrie(root);         }       }       // Returns count of distinct substrings of str     static int countDistinctSubstring(String str)     {         // Construct a Trie of all suffixes         Suffix_trie sTrie = new Suffix_trie(str);           // Return count of nodes in Trie of Suffixes         return sTrie.countNodesInTrie();     }       // Driver program to test above function     public static void Main(String []args)     {         String str = "ababa";         Console.WriteLine("Count of distinct substrings is "                 + countDistinctSubstring(str));               } }   // This code contributed by Rajput-Ji

## Javascript

 // A Javascript program to find the count of distinct substring // of a string using trie data structure // A Suffix Trie (A Trie of all suffixes) Node class SuffixTrieNode {     constructor() {         // Initialize all child pointers as null         this.children = new Array(26).fill(null);     }       // A recursive function to insert a suffix of the s in     // subtree rooted with this node     insertSuffix(suffix) {               // If string has more characters         if (suffix.length > 0) {             // Find the first character and convert it             // into 0-25 range.             const cIndex = suffix.charCodeAt(0) - 'a'.charCodeAt(0);             // If there is no edge for this character,             // add a new edge             if (!this.children[cIndex]) {                 this.children[cIndex] = new SuffixTrieNode();             }             // Recur for next suffix             this.children[cIndex].insertSuffix(suffix.slice(1));         }     } }   // A Trie of all suffixes class SuffixTrie {     constructor(s) {         // Constructor (Builds a trie of suffies of the given text)         this.root = new SuffixTrieNode();         for (let i = 0; i < s.length; i++) {                       // Consider all suffixes of given string and insert             // them into the Suffix Trie using recursive function             // insertSuffix() in SuffixTrieNode class             this.root.insertSuffix(s.slice(i));         }     }       // method to count total nodes in suffix trie     countNodesInTrie() {         return this._countNodesInTrie(this.root);     }       _countNodesInTrie(node) {         // If all characters of pattern have been processed,         if (node === null) {             return 0;         }         let count = 0;         for (let i = 0; i < 26; i++) {                       // if children is not null then find count             // of all nodes in this subtrie             if (node.children[i]) {                 count += this._countNodesInTrie(node.children[i]);             }         }                   // return count of nodes of subtrie and plus         // 1 because of node's own count         return count + 1;     } }   // Returns count of distinct substrings of str function countDistinctSubstring(str) {       // Construct a Trie of all suffixes     const sTrie = new SuffixTrie(str);           // Return count of nodes in Trie of Suffixes     return sTrie.countNodesInTrie(); }   // Driver program to test above function const str = 'ababa'; console.log('Count of distinct substrings is', countDistinctSubstring(str));

Output

Count of distinct substrings is 10

Time Complexity: O(n2), where n is the length of string.
Auxiliary Space: O(n)

We will soon be discussing Suffix Array and Suffix Tree based approaches for this problem. This article is contributed by Utkarsh Trivedi. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

My Personal Notes arrow_drop_up