【洛谷刷题笔记】P3879 [TJOI2010] 阅读理解

题目传送门https://www.luogu.com.cn/problem/P3879

10 pts

思路

妥妥的 Trie 字典树 模板题。

令 exist_{i,j} 表示 最后一个字母编号为 i 的单词在第 j 篇文章中是否出现

代码演示

#include 
#include 
using namespace std;
int n, m;
int trie[500010][26];   // 字典树 
int tot = 0;   // 最大节点编号
bool exist[500010][1010];
char str[1010];
int mapping(char a) {   // 映射字符 
	return a - 'a';
}
void insert(int line, char *str) {   // 将 str 单词加入字典树 
	int u = 0;   // 根节点 
	int len = strlen(str);   // 字符串长度 
	for (int i = 0; i < len; i++) {
		int a = mapping(str[i]);   // 映射字符 
		if (trie[u][a] == 0)   // 没有这个节点 
			trie[u][a] = ++tot;   // 记录该节点 
		u = trie[u][a];   // 跳至该节点 
	} 
	exist[u][line] = 1;   // 标记该单词在第 line 行出现过
}
void find(char *str) {
	int u = 0;   // 根节点 
	int len = strlen(str);   // 字符串长度 
	for (int i = 0; i < len; i++) {
		int a = mapping(str[i]);   // 映射字符
		if (trie[u][a] == 0) {   // 没有这个节点 
			cout << endl;
			return;
		}
		u = trie[u][a];
	} 
	for (int i = 1; i <= n; i++)
		if (exist[u][i]) cout << i << " ";
	cout << endl;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int l;
		cin >> l;
		while (l--) {
			cin >> str;
			insert(i, str);
		}
	} 
	cin >> m;
	while (m--) {
		cin >> str;
		find(str);
	}
	return 0;
}

提交记录

【洛谷刷题笔记】P3879 [TJOI2010] 阅读理解_第1张图片

90 pts

思路

把 exist 数组开到 50010\times 110,用 1 个点的 WA 换 10 个点的 MLE,聪明如我 QaQ!

代码演示

提交记录

【洛谷刷题笔记】P3879 [TJOI2010] 阅读理解_第2张图片

100 pts

思路

绞(kan)尽(le)脑(ti)汁(jie),才发现要用到 bitset

把 exist 数组的类型改为 bitset,节省 32 倍空间,轻松 AC。

代码演示

#include 
#include 
#include    // 别忘了导入头文件
using namespace std;
#define MAXN 1010
int n, m;
int trie[500010][26];   // 字典树 
int tot = 0;   // 最大节点编号
bitset <1010> exist[500010];
char str[1010];
int mapping(char a) {   // 映射字符 
	return a - 'a';
}
void insert(int line, char *str) {   // 将 str 加入字典树 
	int u = 0;   // 根节点 
	int len = strlen(str);   // 字符串长度 
	for (int i = 0; i < len; i++) {
		int a = mapping(str[i]);   // 映射字符 
		if (trie[u][a] == 0)   // 没有这个节点 
			trie[u][a] = ++tot;   // 记录该节点 
		u = trie[u][a];   // 跳至该节点 
	} 
	exist[u][line] = 1;   // 标记
}
void find(char *str) {
	int u = 0;   // 根节点 
	int len = strlen(str);   // 字符串长度 
	for (int i = 0; i < len; i++) {
		int a = mapping(str[i]);   // 映射字符
		if (trie[u][a] == 0) {   // 没有这个节点 
			cout << endl;
			return;
		}
		u = trie[u][a];
	} 
	for (int i = 1; i <= n; i++)
		if (exist[u][i]) cout << i << " ";
	cout << endl;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int l;
		cin >> l;
		while (l--) {
			cin >> str;
			insert(i, str);
		}
	} 
	cin >> m;
	while (m--) {
		cin >> str;
		find(str);
	}
	return 0;
}

提交记录

【洛谷刷题笔记】P3879 [TJOI2010] 阅读理解_第3张图片

个人 OI 水平有限,请见谅。 

--The End--

你可能感兴趣的:(洛谷刷题笔记,c++,蓝桥杯,算法)