trie树 和 树的存储--左儿子右兄弟 --- uva 11732

来源:互联网 发布:福瑞博德软件开发 编辑:程序博客网 时间:2024/05/17 23:48

trie树也叫前缀树 , 是一种字符串的快速查找树 , 有就是一种树。

因为trie树 , 是一种树 ,因此我们先讨论树的存储。


树的存储:左儿子右兄弟

对于普通情况下的树 ,  我们会采用儿子节点法 , 来存储 , 但在trie中 , 往往采用左儿子右兄弟的存储法 , 更为快速

左儿子右兄弟就是说,在树中 , 每个结点有两个指针结点 , 一个指向其儿子 , 一个指向其兄弟。


一下的代码 , 我们是用数组来代替链表的 , 这样更方便。

代码:

#include <iostream>#include <stdio.h>using namespace std;#define maxn 100struct node{char y;int next ; //儿子int right; //兄弟//void clear1()  {next = -1 ;  right = -1;}}trie[maxn];int next = 1;char ch[maxn];void init(){trie[0].next = trie[0].right = -1;}void insert(){int u = 0 , v;int i , j;bool flag;for(i = 0; ch[i] ; i++){flag = false;for(v = trie[u].next ; v != -1; v = trie[v].right){if(trie[v].y == ch[i]){flag = true;break;}}if(!flag){ v = next++;trie[v].right = trie[u].next;trie[u].next = v; trie[v].next = -1;trie[v].y = ch[i];}u = v;}}int main(){return 0;}


uva11732解法:

这个题目一看就知道是用trie树, 来存储每个单词 , 然后每加入一个单词 , 我们就计算需要计算多少次 , 这样就能得到总的次数。然后当我们用普通的树存储方法时 , 就肯定会超时 , 因此需要使用 左儿子右兄弟的存储法。

比较是:

1、两个相同字符              2次

2、两个不同字符              1次

3、'/0' 和 '/0'                      2次

4、'/0' 和其他字符             1次


代码:

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define maxn 4000010struct node{char y;    int son; //指向儿子int right; //指向右边的兄弟节点    int sum ; //表示有多少个儿子}trie[maxn];int ch[123];char str[1010];int n , trie_s ;long long  sum ;void init(){trie[0].son = trie[0].right = -1;trie[0].sum = 0;sum = 0;trie_s = 1;}void insert1(){    int i , j , k = strlen(str);    //int x , y = 0;    int u = 0;bool flag;    for(i = 0; i <= k ; i++)    {flag = false;for(j = trie[u].son ; j != -1 ; j = trie[j].right){if(trie[j].y == str[i]){flag = true;break;}}if(!flag){j = trie_s++;trie[j].right = trie[u].son;trie[j].y = str[i];trie[u].son = j;//trie[u].sum += 1; //记录有多少儿子trie[j].sum = 0;trie[j].son = -1;}        if(i == k) { sum += trie[u].sum+trie[j].sum; trie[j].sum++;} //特判结尾 Trie中不会进入结尾字符,需特判统计        else            sum += (trie[u].sum+trie[j].sum);        trie[u].sum++;        u = j;        //trie[u].sum += 1; //记录有多少儿子//sum += trie[u].sum+trie[j].sum-1;//u = j;    }    //sum += trie[u].sum+trie[u].p*2;//trie[u].p += 1;}int main(){    int cas = 1;    int i ;    while(scanf("%d" , &n) && n)    {init();        for(i = 1; i <= n; i++)        {            scanf("%s" , str);            insert1();        }        cout<<"Case "<<cas++<<": ";        cout<<sum<<endl;//printf("%I64d\n" , sum);    }    return 0;}/*2ab4cathatmatsir0*/


0 0
原创粉丝点击