P2580 于是他错误的点名开始了 字典树
题意:给出n个模式串,给出m个查询串
问每一个查询串是否出现过?如果没出现过,就打印WRONG
如果出现过,则看起被查询了几次,如果到目前为止(包括本次)查询过一次,则输出OK
多次则输出 REPEAT
思路:直接建字典树
跑查询的时候,如果找不到,就返回0
如果已经找到,则用vis数组来标记到目前为止这个串被查询了多少次
然后返回按对应结果输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=5e5+10; //大小开模式串个数*模式串长度 4 char s[100]; 5 int vis[maxn]; 6 int trie[maxn][26]; 7 int tot; 8 void Insert() 9 { 10 int rt=0; 11 for(int i=0;i<strlen(s);i++){ 12 int id=s[i]-'a'; 13 if(!trie[rt][id]) trie[rt][id]=++tot; 14 rt=trie[rt][id]; 15 } 16 } 17 int Search() 18 { 19 int rt=0; 20 for(int i=0;i<strlen(s);i++){ 21 int id=s[i]-'a'; 22 if(!trie[rt][id]) return 0; 23 rt=trie[rt][id]; 24 } //rt经过此循环后变成前缀最后一个字母所在位置 25 vis[rt]++; 26 return vis[rt]; //返回当前字符串结尾节点的访问次数,也就是作为前缀的出现次数 27 } 28 int main() 29 { 30 int n; 31 scanf("%d",&n); 32 for(int i=1;i<=n;i++){ 33 scanf("%s",s); 34 Insert(); 35 } 36 int m; 37 scanf("%d",&m); 38 while(m--){ 39 scanf("%s",s); 40 int tmp=Search(); 41 if(!tmp) printf("WRONG\n"); 42 else if(tmp==1) printf("OK\n"); 43 else printf("REPEAT\n"); 44 } 45 return 0; 46 }