您的位置:首页 > 其它

字符串匹配(二)——Trie:字典树

2018-03-31 11:05 288 查看
一、简介
Trie,又称字典树或前缀树,是一种有序树状的数据结构,用于保存关联数组,其中的键通常是字符串。
二、作用
把许多字符串做成一个字符串集合,并可以对其进行快速查找(本文以求多少个单词是一个句子的前缀为例)。
三、实现
Trie是一个有根树,它必有一个根节点(我们可以把根节点记作0),每一条边都有一个字符权值(也可以取这个字符的ID来当做权值),而节点上存储的则是该节点的单词数目。
我们可以用son[i][j]来表示第i个节点编号为j的儿子,并用w[i]存储第i个节点的单词数目,这样就可以构造出一个Trie了。
构造一个Trie的时间复杂度是O(∑字符串长度),询问时间则为O(最大字符串长度),不过在实际情况中,复杂度也可能会有所减少。
可以说,Trie的效率是比较高的。
四、模板
//题意:输入一个数n,随后读入n个单词s[1]...s
,然后读入一个数m,随后读入m个句子t[1]...t[m],对于每一个句子t[i],求出有多少个单词是它的前缀 
//本代码默认只有小写字母 
#include<bits/stdc++.h>
#define N 1000//字符串最大个数
#define L 100//字符串最大长度
#define C 26//字符总数
using namespace std;
int n,m;
struct Trie
{
int len,son[N*L+5][C],w[N*L+5];//len存储的节点个数,son[]数组用于储存每个节点的子节点,w[]数组存储每个节点的单词数目 
int getID(char x) {return x-'a';} //获取这个字符的ID 
void Insert(string s) //将字符串s插入Trie 
{
int Now=0;
for(int i=0;i<s.length();i++)
{
if(son[Now][getID(s[i])]==0) son[Now][getID(s[i])]=++len;//若当前字符没出现过,就将其加入当前节点的子节点
Now=son[Now][getID(s[i])];//继续往下进行操作 
}
w[Now]++;//最终的Now就是单词节点,将这个节点单词数加1 
}
int get_pre(string s) //查找字符串s的前缀个数 
{
int Now=0,res=0;//res统计结果
for(int i=0;i<s.length();i++) 
{
res+=w[Now];//加上当前节点的单词数 
if(son[Now][getID(s[i])]!=0) Now=son[Now][getID(s[i])];//继续往下进行操作
else return res;//若当前字符不是当前节点的子节点,就返回结果 

return res+w[Now];

} t;
int main()
{
string x;
scanf("%d",&n);
for(int i=1;i<=n;i++) cin>>x,t.Insert(x);
scanf("%d",&m);
for(int i=1;i<=m;i++) cin>>x,printf("%d\n",t.get_pre(x));
return 0;

}

注:如果您通过此文学会了Trie算法,请您点个赞再离开。当然,也欢迎在讨论区指出此文的不足处,作者会及时对此文加以修正
版权声明:转载请注明地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Trie