字典树Trie是一个很简单的数据结构,直接上代码:
const int MAXN = 500005;
int next[MAXN][26], cnt; // 用类似链式前向星的方式存图,next[i][c]表示i号点所连、存储字符为c+'a'的点的编号
void init() // 初始化
{
memset(next, 0, sizeof(next)); // 全部重置为0,表示当前点没有存储字符
cnt = 1;
}
void insert(const string &s) // 插入字符串
{
int cur = 1;
for (auto c : s)
{
// 尽可能重用之前的路径,如果做不到则新建节点
if (!next[cur][c - 'a'])
next[cur][c - 'a'] = ++cnt;
cur = next[cur][c - 'a']; // 继续向下
}
}
这里使用const string&s比string s更有效率,&是引用指针传递,const 表示只读 加快了读取速度
通过字典树查找字符串用叶子代表整体,来确认是否存在,或者最基础的用法查找某个前缀是否出现过,如下所示
bool find_prefix(const string &s) // 查找某个前缀是否出现过
{
int cur = 1;
for (auto c : s)
{
// 沿着前缀所决定的路径往下走,如果中途发现某个节点不存在,说明前缀不存在
if (!next[cur][c - 'a'])
return false;
cur = next[cur][c - 'a'];
}
return true;
}
第一行一个整数 n,表示班上人数。
接下来n 行,每行一个字符串表示其名字(互不相同,且只含小写字母,长度不超过 50)。
第 n+2 行一个整数 m,表示教练报的名字个数。
接下来 m行,每行一个字符串表示教练报的名字(只含小写字母,且长度不超过 50 )。
输出格式
对于每个教练报的名字,输出一行。
如果该名字正确且是第一次出现,输出 OK,如果该名字错误,输出 WRONG,如果该名字正确但不是第一次出现,输出 REPEAT。
这题用哈希表能很快解决,这里是字典树的解法,判断重复再加一个vis数组即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
#include<string.h>
#include<vector>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=5e5+5;
namespace trie
{
int next[maxn][26];
bool vis[maxn],exist[maxn];
int cnt;
void init(){
memset(next,0,sizeof(next));
cnt=1;
}
void insert(const string &s){
int cur=1;
for(auto c:s){
if(!next[cur][c-'a']){
next[cur][c-'a']=++cnt;
}
cur=next[cur][c-'a'];
}
exist[cur]=true;
}
int find(const string &s){
int cur=1,ans;
for(auto c:s){
if(!next[cur][c-'a'])return 0;
cur=next[cur][c-'a'];
}
if(!exist[cur])ans=0;
else if(!vis[cur])ans=1;
else ans=2;
vis[cur]=true;
return ans;
}
}
int main(){
int n;
cin>>n;
string s;
while(n--){
cin>>s;
trie::insert(s);
}
int m;
cin>>m;
while(m--){
cin>>s;
switch(trie::find(s)){
case 0:
cout<<"WRONG"<<endl;
break;
case 1:
cout<<"OK"<<endl;
break;
case 2:
cout<<"REPEAT"<<endl;
}
}
return 0;
}
讲下这里namespace的用法:避免命名重复c++11采用了命名空间namespace来命名,在空间内的 变量只属于内部,namespace Trie作为字典树的专属命名空间。