F06【模板】字典树(Trie)

F06 字典树(Trie)_哔哩哔哩_bilibi

 

P8306 【模板】字典树 - 洛谷

题目:一个文本串是多少模式串的前缀

把所有模式串插入字典树,

字典树上的一条边代表一个字符,一个节点代表一个字符串前缀,

节点标记前缀出现次数。

// 字典树 O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=3e6+5;
int T,n,q;
int ch[N][65],cnt[N],idx; //ch[p][i]:点边数组,对应多叉树

int getnum(char c){
  if(c>='A'&&c<='Z') return c-'A'; //0~25
  else if(c>='a'&&c<='z') return c-'a'+26; //26~51
  else return c-'0'+52; //52~61
}
void insert(string s){
  int p=0;
  for(auto c:s){
    int i=getnum(c);
    if(!ch[p][i]) ch[p][i]=++idx; //从p点走边i到达新点的编号
    p=ch[p][i]; //走到子节点
    cnt[p]++;   //p点之前的前缀的插入次数
  }
}
int query(string s){
  int p=0;
  for(auto c:s){
    int i=getnum(c);
    if(!ch[p][i]) return 0;
    p=ch[p][i];
  }
  return cnt[p];
}
int main(){
  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  cin>>T;
  while(T--){
    cin>>n>>q; string s;
    for(int i=1;i<=n;i++) cin>>s,insert(s);
    for(int i=1;i<=q;i++) cin>>s,cout<<query(s)<<"\n";
  
    for(int i=0;i<=idx;i++)
      for(int j=0;j<65;j++) ch[i][j]=0;
    for(int i=0;i<=idx;i++) cnt[i]=0;  
    idx=0;
  }
  return 0;
}

 

// 哈希法 O(n)
#include<bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
const int B=131;
int n,q;
string str;
unordered_map<ull,int> f;

signed main(){
  ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);
  int T; cin>>T;
  while(T--){
    cin>>n>>q; f.clear();
    for(int i=1; i<=n; ++i){
      cin>>str; ull h=0;
      for(auto j:str) h=h*B+j,f[h]++; //f:前缀哈希值的出现次数
    }
    while(q--){
      cin>>str; ull h=0;
      for(auto i:str) h=h*B+i;
      cout<<f[h]<<'\n';
    }
  }
  return 0;
}

 

字典树 (Trie) - OI Wiki

P2580 于是他错误的点名开始了 - 洛谷

P4407 [JSOI2009] 电子字典 - 洛谷

P6088 [JSOI2015] 字符串树 - 洛谷

P6623 [省选联考 2020 A 卷] 树 - 洛谷

AT_agc057_c [AGC057C] Increment or Xor - 洛谷

 

posted @ 2022-04-15 08:49  董晓  阅读(2332)  评论(3)    收藏  举报