Trie


贴一个大佬的博客

https://www.acwing.com/solution/content/14695/

Trie树长这样:

这个是Trie树的存储

 来自acwing的y总笔记

使用Trie这个数据结构一般题目只有小写字母或者大写字母或者数字等等形式比较单一

 然后在每个单词的结尾最后标记一下,表示这是一个单词并且以某个单词结尾

Trie树的查找:

就对着这个图来搜索就好了,然后看看要搜索的这个字符串,这个图里面有没有

要一一对应相等并且要又这个单词的最后一个数作为结尾标记

来自acw下面的一个评论,说的好清楚呀

 来自acw的最高赞题解

 再上一下之前y总的图,根据代码来理解一下:

void insert(char ch[])
{
    int p=0;
    for(int i=0;ch[i];i++)
    {
        int u=ch[i]-'a';
        if(!son[p][u]) son[p][u]=++idx;//idx表示当前使用的下标,如果当时使用的结点没有伸出u,那就创造一个新的结点
        p=son[p][u];//p这个结点指向下一个(改插入的那个字符),不会重复,因为 idx是自增的 
    }
    cnt[p]++;//全部结束了之后,看看以p这个结点为结尾有多少个 
}
int query(char ch[])
{
    int p=0;
    for(int i=0;ch[i];i++)
    {
        int u=ch[i]-'a';
        if(!son[p][u])
            return 0;
        p=son[p][u];
    }
    return cnt[p];
} 

分别对应了插入和查找的操作,插入懂了之后查找一目了然

#include
using namespace std;
const int N=1e5+10;
int son[N][26];
int cnt[N],idx;//以当前结尾的串有多少个 
void insert(char ch[])
{
    int p=0;
    for(int i=0;ch[i];i++)
    {
        int u=ch[i]-'a';
        if(!son[p][u]) son[p][u]=++idx;//idx表示当前使用的下标,如果当时使用的结点没有伸出u,那就创造一个新的结点
        p=son[p][u];//p这个结点指向下一个(改插入的那个字符),不会重复,因为 idx是自增的 
    }
    cnt[p]++;//全部结束了之后,看看以p这个结点为结尾有多少个 
}
int query(char ch[])
{
    int p=0;
    for(int i=0;ch[i];i++)
    {
        int u=ch[i]-'a';
        if(!son[p][u])
            return 0;
        p=son[p][u];
    }
    return cnt[p];
}
int main(){
    int n;
    cin>>n;
    while(n--)
    {
        char c,ch[100010];
        cin>>c>>ch;
        if(c=='I') insert(ch);
        else printf("%d\n",query(ch));
    }
    return 0;
}