📜  使用Trie打印字典中所有可能的单词组合

📅  最后修改于: 2021-05-24 20:15:09             🧑  作者: Mango

给定一个字符串数组arr [] ,对于该数组中的每个字符串,打印所有可以组合在一起构成该单词的字符串的可能组合。

例子:

Input: arr[] = ["sam", "sung", "samsung"]
Output:
sam: 
    sam
sung: 
    sung
samsung: 
    sam sung
    samsung
String 'samsung' can be formed using two different 
strings from the array i.e. 'sam' and 'sung' whereas 
'samsung' itself is also a string in the array.

Input: arr[] = ["ice", "cream", "icecream"]
Output:
ice: 
    ice
cream: 
    cream
icecream: 
    ice cream
    icecream

方法:

  • 将所有给定的字符串添加到特里。
  • 逐字符处理每个前缀字符,并通过搜索检查是否由trie组成单词。
  • 如果前缀在Trie中存在,则将其添加到结果中,并进一步处理字符串的其余后缀。
  • 一旦到达字符串,请打印找到的所有组合。

下面是上述方法的实现:

CPP
// C++ implementation of the approach
  
#include 
using namespace std;
  
const int ALPHABET_SIZE = 26;
  
// Trie node
struct TrieNode {
    struct TrieNode* children[ALPHABET_SIZE];
  
    // isEndOfWord is true if node
    // represents the end of the word
    bool isEndOfWord;
};
  
// Returns new trie node
struct TrieNode*
getNode(void)
{
    struct TrieNode* pNode = new TrieNode;
  
    pNode->isEndOfWord = false;
  
    for (int i = 0; i < ALPHABET_SIZE; i++)
        pNode->children[i] = NULL;
  
    return pNode;
}
  
// If not present, inserts key into trie
// If the key is prefix of trie node,
// marks the node as leaf node
void insert(struct TrieNode* root, string key)
{
    struct TrieNode* pCrawl = root;
  
    for (int i = 0; i < key.length(); i++) {
        int index = key[i] - 'a';
        if (!pCrawl->children[index])
            pCrawl->children[index] = getNode();
  
        pCrawl = pCrawl->children[index];
    }
  
    // Mark node as leaf
    pCrawl->isEndOfWord = true;
}
  
// Returns true if the key is present in the trie
bool search(struct TrieNode* root, string key)
{
    struct TrieNode* pCrawl = root;
  
    for (int i = 0; i < key.length(); i++) {
        int index = key[i] - 'a';
        if (!pCrawl->children[index])
            return false;
  
        pCrawl = pCrawl->children[index];
    }
  
    return (pCrawl != NULL && pCrawl->isEndOfWord);
}
  
// Result stores the current prefix with
// spaces between words
void wordBreakAll(TrieNode* root,
                  string word, int n, string result)
{
    // Process all prefixes one by one
    for (int i = 1; i <= n; i++) {
  
        // Extract substring from 0 to i in prefix
        string prefix = word.substr(0, i);
  
        // If trie conatins this prefix then check
        // for the remaining string.
        // Otherwise ignore this prefix
        if (search(root, prefix)) {
  
            // If no more elements are there then print
            if (i == n) {
  
                // Add this element to the previous prefix
                result += prefix;
  
                // If(result == word) then return
                // If you don't want to print last word
                cout << "\t" << result << endl;
                return;
            }
            wordBreakAll(root, word.substr(i, n - i), n - i,
                         result + prefix + " ");
        }
    }
}
  
// Driver code
int main()
{
    struct TrieNode* root = getNode();
  
    string dictionary[] = {
        "sam", "sung",
        "samsung"
    };
    int n = sizeof(dictionary) / sizeof(string);
  
    for (int i = 0; i < n; i++) {
        insert(root, dictionary[i]);
    }
  
    for (int i = 0; i < n; i++) {
        cout << dictionary[i] << ": \n";
        wordBreakAll(root, dictionary[i],
                     dictionary[i].length(), "");
    }
  
    return 0;
}


Java
// Java implementation of the approach
class GFG
{
  
static int ALPHABET_SIZE = 26;
  
// Trie node
static class TrieNode
{
    TrieNode []children = 
    new TrieNode[ALPHABET_SIZE];
  
    // isEndOfWord is true if node
    // represents the end of the word
    boolean isEndOfWord;
  
    public TrieNode()
    {
        super();
    }
      
};
  
// Returns new trie node
static TrieNode getNode()
{
    TrieNode pNode = new TrieNode();
  
    pNode.isEndOfWord = false;
  
    for (int i = 0; i < ALPHABET_SIZE; i++)
        pNode.children[i] = null;
  
    return pNode;
}
  
// If not present, inserts key into trie
// If the key is prefix of trie node,
// marks the node as leaf node
static void insert(TrieNode root, String key)
{
    TrieNode pCrawl = root;
  
    for (int i = 0; i < key.length(); i++)
    {
        int index = key.charAt(i) - 'a';
        if (pCrawl.children[index] == null)
            pCrawl.children[index] = getNode();
  
        pCrawl = pCrawl.children[index];
    }
  
    // Mark node as leaf
    pCrawl.isEndOfWord = true;
}
  
// Returns true if the key is present in the trie
static boolean search(TrieNode root, String key)
{
    TrieNode pCrawl = root;
  
    for (int i = 0; i < key.length(); i++)
    {
        int index = key.charAt(i) - 'a';
        if (pCrawl.children[index] == null)
            return false;
  
        pCrawl = pCrawl.children[index];
    }
  
    return (pCrawl != null && pCrawl.isEndOfWord);
}
  
// Result stores the current prefix with
// spaces between words
static void wordBreakAll(TrieNode root,
                String word, int n, String result)
{
    // Process all prefixes one by one
    for (int i = 1; i <= n; i++) 
    {
  
        // Extract subString from 0 to i in prefix
        String prefix = word.substring(0, i);
  
        // If trie conatins this prefix then check
        // for the remaining String.
        // Otherwise ignore this prefix
        if (search(root, prefix))
        {
  
            // If no more elements are there then print
            if (i == n) 
            {
  
                // Add this element to the previous prefix
                result += prefix;
  
                // If(result == word) then return
                // If you don't want to print last word
                System.out.print("\t" + result +"\n");
                return;
            }
            wordBreakAll(root, word.substring(i, n), n - i,
                        result + prefix + " ");
        }
    }
}
  
// Driver code
public static void main(String[] args)
{
    new TrieNode();
    TrieNode root = getNode();
  
    String dictionary[] = {"sam", "sung",
                            "samsung"};
    int n = dictionary.length;
  
    for (int i = 0; i < n; i++)
    {
        insert(root, dictionary[i]);
    }
  
    for (int i = 0; i < n; i++)
    {
        System.out.print(dictionary[i]+ ": \n");
        wordBreakAll(root, dictionary[i],
                    dictionary[i].length(), "");
    }
}
}
  
// This code is contributed by PrinciRaj1992


C#
// C# implementation of the approach
using System;
  
class GFG
{
  
static int ALPHABET_SIZE = 26;
  
// Trie node
class TrieNode
{
    public TrieNode []children = 
    new TrieNode[ALPHABET_SIZE];
  
    // isEndOfWord is true if node
    // represents the end of the word
    public bool isEndOfWord;
  
    public TrieNode()
    {
    }
      
};
  
// Returns new trie node
static TrieNode getNode()
{
    TrieNode pNode = new TrieNode();
  
    pNode.isEndOfWord = false;
  
    for (int i = 0; i < ALPHABET_SIZE; i++)
        pNode.children[i] = null;
  
    return pNode;
}
  
// If not present, inserts key into trie
// If the key is prefix of trie node,
// marks the node as leaf node
static void insert(TrieNode root, String key)
{
    TrieNode pCrawl = root;
  
    for (int i = 0; i < key.Length; i++)
    {
        int index = key[i] - 'a';
        if (pCrawl.children[index] == null)
            pCrawl.children[index] = getNode();
  
        pCrawl = pCrawl.children[index];
    }
  
    // Mark node as leaf
    pCrawl.isEndOfWord = true;
}
  
// Returns true if the key is present in the trie
static bool search(TrieNode root, String key)
{
    TrieNode pCrawl = root;
  
    for (int i = 0; i < key.Length; i++)
    {
        int index = key[i] - 'a';
        if (pCrawl.children[index] == null)
            return false;
  
        pCrawl = pCrawl.children[index];
    }
  
    return (pCrawl != null && pCrawl.isEndOfWord);
}
  
// Result stores the current prefix with
// spaces between words
static void wordBreakAll(TrieNode root,
                String word, int n, String result)
{
    // Process all prefixes one by one
    for (int i = 1; i <= n; i++) 
    {
  
        // Extract subString from 0 to i in prefix
        String prefix = word.Substring(0, i);
  
        // If trie conatins this prefix then check
        // for the remaining String.
        // Otherwise ignore this prefix
        if (search(root, prefix))
        {
  
            // If no more elements are there then print
            if (i == n) 
            {
  
                // Add this element to the previous prefix
                result += prefix;
  
                // If(result == word) then return
                // If you don't want to print last word
                Console.Write("\t" + result +"\n");
                return;
            }
            wordBreakAll(root, word.Substring(i, n - i), n - i,
                        result + prefix + " ");
        }
    }
}
  
// Driver code
public static void Main(String[] args)
{
    new TrieNode();
    TrieNode root = getNode();
  
    String []dictionary = {"sam", "sung",
                            "samsung"};
    int n = dictionary.Length;
  
    for (int i = 0; i < n; i++)
    {
        insert(root, dictionary[i]);
    }
  
    for (int i = 0; i < n; i++)
    {
        Console.Write(dictionary[i]+ ": \n");
        wordBreakAll(root, dictionary[i],
                    dictionary[i].Length, "");
    }
}
}
  
// This code is contributed by PrinciRaj1992


输出:
sam: 
    sam
sung: 
    sung
samsung: 
    sam sung
    samsung