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;}