2024.3.21 字典树

字典树

字典树的是一个外向树, 边权为一个字母, 一个节点连向儿子边的权值互不相同, 点权为根到当前节点的权值经过的字符串拼起来。

如果要查找某一个元素的位置, 从根节点开始. 找到相应位置, 如果没有当前这个点, 新建这个点。

由于字典树的性质 : 当前节点的权值是所以的儿子节点的权值的前缀, 所以可以快速求出数量

luoguP8306

模板题, 按上述方法模拟

#include<bits/stdc++.h>

using namespace std;

const int N = 3e6 + 5;

string s;
int n, q, T;

struct TRIE{
  int tot = 1, u;
  struct Node{
    int son[62];
    int cnt;
    void clear(){
      for(int i = 0; i < 62; ++i){
        son[i] = 0;
      }
      cnt = 0;
    }
  }trie[N];
  int con(char c){
    return (c <= 'z' && c >= 'a' ? c - 'a' + 26 : c <= 'Z' && c >= 'A' ? c - 'A' : c - '0' + 52);
  }
  void Insert(string s){
    u = 1;
    for(auto c : s){
      if(!trie[u].son[con(c)]){
        trie[u].son[con(c)] = ++tot;
        trie[tot].clear();
      }
      trie[u].cnt++;
      u = trie[u].son[con(c)];
    }
    trie[u].cnt++;
  }
  int query(string s){
    u = 1;
    for(char c : s){
      if(!trie[u].son[con(c)]){
        return 0;
      }
      u = trie[u].son[con(c)];
    }
    return trie[u].cnt;
  }
}a;

void S(){
  a.tot = 1;
  a.trie[1].clear();
  cin >> n >> q;
  for(int i = 1; i <= n; ++i){
    cin >> s;
    a.Insert(s);
  }
  for(int i = 1; i <= q; ++i){
    cin >> s;
    cout << a.query(s) << '\n';
  }
}

int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  for(cin >> T; T--; S()){
  }
  return 0;
}
posted @ 2024-03-21 16:59  liuyichen  阅读(4)  评论(0编辑  收藏  举报