【AcWing基础题】TriesTree

此算法用于快速存储以及快速查找字符串

流程图

image

代码


#include <iostream>
using namespace std;
const int N = 100010;
//题目给定的是小写的英文字母,每个节点最多向外连26个边
//son数组的第一维是:父节点对应的idx
int son[N][26];
//cnt 是以当前这个点结尾的单词有多少个,idx表示当前用到了哪个下标  idx初始化为0
// 下标是0的点,既是根节点,又是空节点
int cnt[N], idx;
char str[N];
//存储也就是插入操作
void insert(char str[])
{
  int p = 0;
  //遍历字符串
  for (int i = 0; str[i]; i++)
  {
    // 把当前字母 对应的子节点编号 搞出来
    //把字母a-z 映射成0~25
    // 因为'a' 的ascii 对应的是97  ,任何一个小写字母- 97 就是对应的位置。
    int u = str[i] - 'a';
    // 如果p节点没有u这个儿子,就把他创建出来
    if (son[p][u] == 0)
    {
      son[p][u] = ++idx;
    }
    //走到下一个节点
    p = son[p][u];
  }
  // 表示以这个点结尾的单词数量多了一个
//为什么不担心重复呢? 因为每个单词所给定的ascii值是不一样的,那么累加起来的p值【son[][]就是一个值呀】
//也是不一样的。那么如果P值一样,说明字符串一致呀,那么肯定加1啊
  cnt[p]++;
}
int query(char str[])
{
  int p = 0;
  for (int i = 0; str[i]; i++)
  {
    int u = str[i] - 'a';
    if (!son[p][u])
    {
      return 0;
    }
    p = son[p][u];
  }
  return cnt[p];
}
int main()
{
  int n;
  scanf("%d", &n);
  while (n--)
  {
    char op[2];
    scanf("%s%s", op, str);
    if (op[0] == 'I')
    {
      insert(str);
    }
    else
    {
      printf("%d\n", query(str));
    }
  }
  return 0;
}


posted @ 2021-10-23 10:44  取我方天画戟来  阅读(38)  评论(0)    收藏  举报