首页 > 技术文章 > 洛谷P2580 - 于是他错误的点名开始了(字典树模板题)

Hayasaka 2020-08-07 11:43 原文

在这里插入图片描述在这里插入图片描述

题目大意:

第一行输入一个 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;
}

推荐阅读