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