P2580 于是他错误的点名开始了

题目来自洛谷网站:

字典树思路:

①将数据全部存入到字典树中,同时,将字符串结尾字符的编号存入到st数组中。
②在对名字查找前,判断一下,如果名字没出现在集合中:check.count(x)==0,那么名字就不是重复的名字了。如果返回的是1的话,那么这个名字就重复了。
③在字典树中查找教练说的名字,如果没找到,直接返回false。如果找到了,返回st[p]。st[p]为true,则名字正确,为false,名字错误。

④本题注意数据范围,最多有1e4个名字,每个名字最多有50个字母。 N = 1e4*50

字典树代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5;

int n, m;
//字典树trie 编号idx
int trie[N][27], idx;
//存的是编号 记录字符串是以什么字符结尾
bool st[N];
//判断是否重复
unordered_set<string> check;

//存入字典树
void add(string x){
    //指针0开始
    int p = 0;
    for(auto i:x){
        //找到i字符的映射值
        int j = i - 'a';
        //树中没有
        if(!trie[p][j]){
            trie[p][j] = ++idx;
        }
        //trie[p][j] 作为新的节点
        p = trie[p][j];
    }
    st[p] = true;
}

//在字典树中查找
bool query(string x){
    int p = 0;
    for(auto i: x){
        int j = i-'a';
        if(!trie[p][j]){
            return false;
        }
        p = trie[p][j];
    }
    //判断一下结尾是否存过
    return st[p];
}

signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        string x; cin >> x;
        //存入
        add(x);
    }
    //查找
    cin >> m;
    while(m--){
        string x; cin >> x;
        //判断有没有重复
        if(!check.count(x)){
            if(query(x)) cout << "OK" << endl;
            else cout << "WRONG" << endl;
            check.insert(x);
        }
        else cout << "REPEAT" << endl;
    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值