数据结构-字符串-字典树
字典树就是著名的 树,是未来学很多字符串自动机的必备前置知识。
用处:插入字符串,查找字符串出现次数。
这个数据结构就是一个有根树,根节点编号为 。除了根节点外,每个节点上有一个字母。对于每个节点 , 表示这个节点的儿子中字符为 的那个的编号, 表示插入的字符串中以这个节点为结尾的字符串数。
每当要插入一个字符串 (下标从 开始)时,就从根节点 开始,如果根节点 没有字符为 的子节点,就创造一个那个节点,然后无论那个节点是不是刚被创造出来的,走到那个节点。然后再看那个节点有没有字符为 的子节点,然后如此操作,走到 (字符串长度为 )时, 单前节点 。
查找字符串 时,也从根节点 开始,沿着 数组走,如果发现某次节点没有字符串 的单前字符子节点,那么久说明字符串 以前没有出现过。否则,走到 时,可得 字符串出现的次数就为 单前节点 。
如果我们插入了这些字符串:
那么字典树就长这样(黄色数字为节点的
,没有黄色数字表示
为
):
由于字符的种类只有
,而且正常英文单词的长度不会超过
,所以可以保证字典树空间复杂度和时间复杂度不超标,每次插入查询都是
的。
如果你已经掌握了这些知识,那么蒟蒻就放代码了:
class trie{
public:
int ch[N][30],cnt,mk[N];
trie(){cnt=1;}
void insert(char*s){
int n=strlen(s+1),x=1;
for(int i=1;i<=n;i++){
int c=s[i]-'a'+1;
if(!ch[x][c]) ch[x][c]=++cnt;
x=ch[x][c];
}
mk[x]++;
}
int find(char*s){
int n=strlen(s+1),x=1;
for(int i=1;i<=n;i++){
int c=s[i]-'a'+1;
if(!ch[x][c]) return 0;
x=ch[x][c];
}
return mk[x];
}
}t;
学字符串道路:
祝大家学习快乐!