洛谷P2580 - 于是他错误的点名开始了(字典树模板题)
题目大意:
第一行输入一个 n 表示有 n 个人,接下来输入 n 个人的名字,再输入一个q 表示有 q 次询问,接下来输入q行人名,对于每个询问,如果该人名是第一次被点到,则输出 ok ,如果之前点过了,则输出repeat ,如果查无此人就输出 wrong (均为大写)。
解题思路:
Trie树模板题,根据输入的串建树,字典树实质上也可以理解为26叉树,然后询问时只需要看是否匹配就可以了,如果第一次匹配则匹配到以后改一下cnt值,如果不存在(匹配不到)就直接wrong就可以了。
Code(Trie树做法):
#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 50;
int ch[N * 32][26], cnt[N * 32], tot = 1;
void insert(string s)//建树的过程
{
int u = 0;
for (int i = 0; i < s.size(); i ++)
{
int v = s[i] - 'a';
if (!ch[u][v]) ch[u][v] = tot++;
u = ch[u][v];
}
cnt[u] = 1;
}
void solve(string s)//在字典中检索的过程
{
int u = 0;
for (int i = 0; i < s.size(); i ++)
{
int v = s[i] - 'a';
if (! ch[u][v]) break;
u = ch[u][v];
}
if (cnt[u] == 1)
{
puts("OK");
cnt[u] = 2;
}
else if (cnt[u] == 2)
puts("REPEAT");
else
puts("WRONG");
}
int main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
string s;
while (n--)
{
cin >> s;
insert(s);
}
cin >> n;
while (n--)
{
cin >> s;
solve(s);
}
return 0;
}
这道题还有STL做法,即用map存一下,出现过的赋值1,点过名的赋值2,不存在的默认为0,用map映射一下也可以
Code(STL做法):
#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 150;
map<string , int > mp;
int main()
{
int t;
cin >> t;
while (t--)
{
string a;
cin >> a;
mp[a] = 1;
}
cin >> t;
while (t--)
{
string a;
cin >> a;
if (mp[a] == 1)
{
mp[a] = 2;
cout << "OK" << endl;
}
else if (mp[a] == 2)
cout << "REPEAT" << endl;
else
cout << "WRONG" << endl;
}
return 0;
}