题目
题目传送门:https://www.acwing.com/problem/content/144/
给定N个字符串S1,S2…SNS1,S2…SN,接下来进行M次询问,每次询问给定一个字符串T,求S1S1~SNSN中有多少个字符串是T的前缀。
输入字符串的总长度不超过106106,仅包含小写字母。
输入格式
第一行输入两个整数N,M。
接下来N行每行输入一个字符串SiSi。
接下来M行每行一个字符串T用以询问。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
输入样例:
输出样例:
题解
用前n个字符串构建Trie,然后查询后m个字符串即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=(int)1e6+10;
int tot,root,trie[maxn][26]; int flag[maxn]; char s[maxn];
void Trie(){ memset(trie[1],0,sizeof(trie[1])); flag[1]=1; root=tot=1; }
void insert(const char *str){ int *cur=&root; for(const char* p=str;*p;p++){ cur=&trie[*cur][*p-'a']; if(*cur==0){ *cur=++tot; memset(trie[tot],0,sizeof(trie[tot])); flag[tot]=0; } } flag[*cur]++; }
int query(const char* str){ int ans=0; int *cur=&root; for(const char *p=str;*p&&*cur;p++) { cur = &trie[*cur][*p - 'a']; if(!*cur) return ans; ans+=flag[*cur]; } return ans; }
int main(){ int n,m; scanf("%d%d",&n,&m); Trie(); while(n--){ scanf("%s",s); insert(s); } while(m--){ scanf("%s",s); printf("%d\n",query(s)); } return 0; }
|