字典树Trie树的应用

问题:有若干个字符串,求他们的最长公共前缀子串。

解法:该问题的一个比较好的办法是使用Trie树。因为Trie树有明显的字符串前缀特征。在查询近似前缀的时候经常用到。这里我建立了Trie树,且为了寻找最长公共前缀子串更方便,对结点加入了分支个数属性branch和出现次数属性times。这样,把所有字符串加入Trie树之后,通过根结点出发寻找单分支路径且出现次数均为字符串集个数,就可以找到结果。


代码:

[cpp]  view plain copy
  1. #include <string>  
  2. #include <iostream>  
  3. #include <vector>  
  4. #include <malloc.h>  
  5. using namespace std;  
  6. #define N 26  
  7.   
  8. typedef struct node {   
  9.     char ch;  
  10.     int branch ; //记录分支树,方便最后查询  
  11.     int times;  
  12.     node* child[N];  
  13. }node, *Trie;  
  14.   
  15. Trie init_Trie()  
  16. {  
  17.     Trie root = (node*)malloc(sizeof(node)); //Trie树的根节点不存储数据  
  18.     root->branch = 0;  
  19.     root->times = 0;  
  20.     for(int i=0;i<N;i++)  
  21.         root->child[i] = NULL;  
  22.     return root;  
  23. }  
  24.   
  25. void insert_Trie(Trie root, const string str)  
  26. {  
  27.     int n = str.length();  
  28.     if(n == 0)  
  29.     {  
  30.         root->times ++;  
  31.         return;  
  32.     }  
  33.     int i=0;  
  34.     int idx;  
  35.     node *p = root;  
  36.     root->times++;  
  37.     while(i<n)  
  38.     {  
  39.         idx = str[i] - 'a';  
  40.         if(p->child[idx] != NULL)  
  41.         {  
  42.             p = p->child[idx];  
  43.             p->times ++;  
  44.             i++;  
  45.         }  
  46.         else  
  47.         {  
  48.             node* tmp = (node*)malloc(sizeof(node));  
  49.             tmp->ch = str[i];  
  50.             tmp->branch = 0;  
  51.             tmp->times = 1;  
  52.             for(int j=0;j<N;j++)  
  53.                 tmp->child[j] = NULL;  
  54.   
  55.             p->branch ++;  
  56.             p->child[idx] = tmp;  
  57.             p = tmp;  
  58.             i++;  
  59.         }  
  60.     }  
  61. }  
  62.   
  63. string longestCommonPrefix(vector<string> &strs)  
  64. {  
  65.     int n = strs.size();  
  66.     if(n == 0)  
  67.         return "";  
  68.   
  69.     int i;  
  70.     Trie root = init_Trie();  
  71.     for(i=0;i<n;i++)  
  72.         insert_Trie(root, strs[i]);  
  73.   
  74.     i = 0;  
  75.     node* p = root;  
  76.     while(i<strs[0].length() && p->branch == 1 && p->times == n)  
  77.     {  
  78.         p = p->child[strs[0][i] - 'a'];  
  79.         i++;  
  80.     }  
  81.     if(p->times < n)  
  82.         i--;  
  83.     return strs[0].substr(0,i);  
  84. }  
  85.   
  86. int main()  
  87. {  
  88.     vector<string> strs;  
  89.     strs.push_back("a");  
  90.     strs.push_back("aa");  
  91.     //strs.push_back("abcd");  
  92.     string result = longestCommonPrefix(strs);  
  93.     cout<<result<<endl;  
  94.     return 1;  
  95. }  

你可能感兴趣的:(字典树Trie树的应用)