当前位置
- 字符串部分
- Trie树
- KMP
- AC自动机
字符串
Trie树
1.给出n个单词和m个询问,每次询问一个单词,问这个单词是否在单词表中出现过?
答:用map!2.给出n个单词和m个询问,每次询问一个前缀,问是多少个单词的前缀?
答:用Trie树!
1.1 概念
Trie又称字典树,前缀树(事实上前缀树这个名字就很好的解释了Trie的储存方式),是典型的的用空间换时间的做法
来一张图理解一下Trie树
Trie的特点
- Trie的根节点是空的
- 除根节点外,每个节点储存一个单词/字母
- 也就是说,从根节点到每个单词节点的路径上的所有字母连接而成的字符串就是该节点对应的字符串
- 每个叶子结点作为一个单词的结尾
- 每个非叶子结点一般会被多次使用,以节省遍历时的时间效率
1.2 结构
struct node{
int son[27];
bool flag;
int cnt;//用于辅助使用
node(){
cnt=0;
memset(son,0,sizeof son);
flag=false;
}
}trie[maxn];
1.3 常用操作
插入
void insert(char *s)
{
int v,len=strlen(s);
int u=0;
for(int i=0;i<len;i++)
{
v=s[i]-'a';
if(!trie[u].son[v])
trie[u].son[v]=++num;
u=trie[u].son[v];
}
trie[u].flag=1;
}
查询
int find(char *s)
{
int v, u = 0, len=strlen(s);
for(int i=0;i<len;i++)
{
v=s[i]-'a';
if(!trie[u].son[v])
return 3;//WRONG——字典树中没有该字
u=trie[u].son[v];
}
if(!trie[u].flag)
return 3;//WRONG——字典树中没有该单词
if(!trie[u].cnt)//该单词未点名过
{
trie[u].cnt++;
return 1;//OK
}
else return 2;
}
1.4 练习题
- hdu 1251 统计难题 http://acm.hdu.edu.cn/showproblem.php?pid=1251
- Luogu P2580 于是他错误的点名开始了
- codevs 4189 字典 http://codevs.cn/problem/4189/