看题解的请直接跳到模板
学Trie树的推荐 这篇文章
算法用途
又称单词查找树,字典树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。(无脑贴百科^_^)
算法思想
每次将一个字符串保存到树中,在查询时利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。
感觉Trie相对而言还是比较好理解的,具体看模板注释,这里就不多讲了。
模板
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 500000
using namespace std;
int n,m,k;
int son[MAXN+5][26];//son[i][j]存的是第i号节点第j个字符的子节点。
char s[55];
bool ex[MAXN+5],f[MAXN+5];//ex判 断这个人名是否出现过,f判 断以这个节点为结尾的是否是人名
int calc(char c){
return c-'a';
}
//插入
void nsrt(char s[]){
int now=0;//当前节点的编号
for (int i=0;s[i];i++){
if (!son[now][calc(s[i])])//如果这个节点的儿子并没有出现过
son[now][calc(s[i])]=++k;//加一个节点当他的儿子
now=son[now][calc(s[i])];//继续循环
}
f[now]=true;//以这个节点为结尾字符串的是人名
}
//查询
int srch(char s[]){
int now=0;
for (int i=0;s[i];i++){
if (!son[now][calc(s[i])])//如果这个人名根本没有出现过
return 2;
now=son[now][calc(s[i])];//继续循环
}
if (!ex[now]){//如果这个人还没被点到
ex[now]=true;//打上标记
return 0;
}
//如果这个人已经点到过了
return 1;
}
int main(){
scanf("%d",&n);
k=0;
memset(son,0,sizeof(son));
memset(f,false,sizeof(f));
memset(ex,false,sizeof(ex));
for (int i=1;i<=n;i++){
scanf("%s",s);
nsrt(s);//插入
}
scanf("%d",&m);
for (int i=1;i<=m;i++){
scanf("%s",s);
int flag=srch(s);//查询
switch (flag){
case 0:{
printf("OK\n");
break;
}
case 1:{
printf("REPEAT\n");
break;
}
default:{
printf("WRONG\n");
break;
}
}
}
return 0;
}