P8306 【模板】字典树
题目链接:https://www.luogu.com.cn/problem/P8306
逻辑清楚,样例通过,提交RE,实在找不出
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=3e5+10; 7 int t, n, q; 8 int di(char c){//字符转数字 9 if(c>='0' && c<='9')return c-'0'; 10 if(c>='A' && c<='Z')return c-'A'+10; 11 if(c>='a' && c<='z')return c-'a'+36; 12 } 13 char dc(int i){//数字转字符 14 if(i>=0 && i<=9)return char(i-0+'0'); 15 if(i>=10 && i<=35) return char(i-10+'A'); 16 if(i>=36 && i<=61) return char(i-36+'a'); 17 } 18 int trie[maxn][62], tot; 19 bool ed[maxn];//用于字符串结束标志 20 void inif(){ 21 memset(trie, 0, sizeof(trie)); 22 memset(ed, 0, sizeof(ed)); 23 tot=1;//标记数组 24 } 25 void trie_build(char s[]){ 26 int len=strlen(s); 27 int p=1; 28 for(int i=0; i<len; i++){ 29 int t=di(s[i]);//转换成每个字符对应的数字下标 30 if(!trie[p][t]) 31 trie[p][t]=++tot; 32 p=trie[p][t]; 33 } 34 ed[p]=true;//标记单词结束 35 } 36 37 void dfs_test(int r){//dfs主要是为了测试 38 for(int i=0; i<62; i++){ 39 if(trie[r][i]){ 40 printf("%c", dc(i)); 41 dfs_test(trie[r][i]); 42 } 43 } 44 printf("\n"); 45 } 46 int dfs(int r){//通过dfs统计所有终点的节点 47 int ret=0; 48 if(ed[r]) ret++;//有终点时 49 for(int i=0; i<62; i++){ 50 if(trie[r][i]) 51 ret+=dfs(trie[r][i]); 52 } 53 return ret; 54 } 55 int trie_query(char s[]){//查前缀数 56 int ret=0; 57 int len=strlen(s); 58 int p=1; 59 for(int i=0; i<len; i++){ 60 int t=di(s[i]);//转换成每个字符对应的数字下标 61 if(trie[p][t])//能匹配时继续往下找 62 p=trie[p][t]; 63 else//不能匹配时返回0 64 return 0; 65 } 66 ret+=dfs(p);//匹配晚字符串s后,从p点继续搜索有多少个单词 67 return ret; 68 } 69 70 int main() 71 { 72 scanf("%d", &t); 73 while(t--){ 74 inif();//每次初始化 75 scanf("%d%d", &n, &q); 76 for(int i=1; i<=n; i++){ 77 char str[3000]; 78 scanf("%s", str); 79 trie_build(str); 80 } 81 while(q--){ 82 char str[3000]; 83 scanf("%s", str); 84 printf("%d\n", trie_query(str)); 85 } 86 } 87 return 0; 88 }