Trie

来源:互联网 发布:软件自动升级程序 编辑:程序博客网 时间:2024/05/29 19:05

Trie 树即为字典树
这个树可以把所有我们要在文本中所查询的前缀都记录下来
当我们拿到一个文本串 需要从里面找出所有前缀串的数目我们就可以用这个结构
拿着我们的文本到这个树里面走一走就得到有多少个前缀了

我们来看 当我们拿到一个前缀
不断地把这个前缀插入到树中
对每一个节点 可以连到26个分节点去
这个树具体有两个操作
一个是add操作
还有一个就是匹配操作

建立过程
Trie的头结点是空的
我们将我们想要统计的串加入到以头结点为根的树里
每一个前缀都是从根节点的一条路径

我们可以看一道例题HDU 1251
输入多个单词
然后再输入多个前缀 每一个前缀输出字符串中出现当前前缀的单词数量

这里我们就可以把所有单词全部add到字典树中
为他们建立查询路径
比如这里的trie的结构我们可以这么设置

struct node{    int time;    node *next[26];    init(){        time = 0;        for(int i=0;i<26;i++)next[i] = NULL;    }}e;

time就记录这里当前前缀已经走过多少次 也就是add过多少次
next表示 指向后面的字符的指针数组

add操作

void add(char s[]){    int len = strlen(s);    node *p = &e; //指向trie的指针    for(int i=0;i<len;i++){        if(!(p->next[s[i]-'a'])){//如果走到这里为空 就重新申请            node *q = (node*)malloc(sizeof(node));            (*q).init();                p->next[s[i]-'a']=q;        }        p = p->next[s[i]-'a'];        p->time++;//并记录前缀次数}

查询:

int match(char s[]){    int len = strlen(s);    node *p = &e;    for(int i=0;i<len;i++){        if(p->next[s[i]-'a']==NULL)return 0;        p = p->next[s[i]-'a'];    }    return p->time;}

这里也就是把我们所要查找的串拿进来一个个匹配 看看能匹配到多少个
返回我们记录的次数

完整代码为:

#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;struct node{    int time;    node *next[26];    void init(){        time = 0;        for(int i=0;i<26;i++)next[i] = NULL;    }}e;void add(char s[]){    int len = strlen(s);    node *p = &e;     for(int i=0;i<len;i++){        if(!(p->next[s[i]-'a'])){            node *q = (node*)malloc(sizeof(node));            (*q).init();                p->next[s[i]-'a']=q;        }        p = p->next[s[i]-'a'];        p->time++;    }}int match(char s[]){    int len = strlen(s);    node *p = &e;    for(int i=0;i<len;i++){        if(p->next[s[i]-'a']==NULL)return 0;        p = p->next[s[i]-'a'];    }    return p->time;}char a[15];int main(){    e.init();    while(*gets(a))add(a);    while(~scanf("%s",a))    {        printf("%d\n",match(a));    }    return 0;} 
原创粉丝点击