【洛谷】 P3879 [TJOI2010]阅读理解
·
【洛谷】 P3879 [TJOI2010]阅读理解
0.总结
Get to the points first. The article comes from LawsonAbs!
- trie树
- 二维数组隐式越界坑
1.题意
判断一个单词是否出现在某串文本中。如果出现,则输出文本的序号【按照从小到大的方式】,否则直接输出换行。
2.分析
典型的模板题,使用 trie 就可以解决。这里我不再介绍trie树了,简单说一下我的主要解决步骤:
- step 1.使用一个trie 数组用于存储每串文本的结构。由题意知,可以设计一个三维数组
trie[][][],其中第一维表示的是第几篇阅读;第二维表示节点个数;第三维表示指向【类同二维的tried数组】 - step 2.依次遍历每个查询字符串,然后输出即可。
3.代码
// Created by lawson on 20-6-21.
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxN = 1005; //表示最大的短文数,同时也作为最大的个数
const int maxM = 20000;
int n,m;//n表示短文数
short trie[maxN][maxM][27];// 26个小写字母
int p = 0,cnt = 1,tot = 0;//cnt 表示第几篇短文;
bool endF[maxN][maxN];//结束标志 => 用bool省空间
void build(char in[] ){
int p = 0;
for(int i = 0;i<strlen(in);i++){
int cNum = in[i]-'a';
if(!trie[cnt][p][cNum]){//如果没有记录
trie[cnt][p][cNum] = ++tot;
}
p = trie[cnt][p][cNum];//更新p的值
}
endF[cnt][p] = true;
}
//查询in这个字符串是否在trie树中
bool search(int index,char in[]){
p = 0;
for(int i = 0;i<strlen(in);i++){
int cNum = in[i]-'a';
if(!trie[index][p][cNum])
return false;
else
p = trie[index][p][cNum];
}
if(endF[index][p])
return true;
return false;
}
int main(){
scanf("%d",&n);
while(cnt<=n){
tot = 0;//重置为0
scanf("%d",&m);
char word[30];//每个字符长20
for(int i = 1;i<=m;i++){
scanf("%s",word);//输入每个单词
build(word);
}
cnt++;
}
scanf("%d",&m);
char query[25];//待查询的字符串
for(int i = 1;i<= m;i++){
int res[maxN];//存储答案
cnt = 0;//重置
scanf("%s",query);
for(int j = 1;j<=n;j++)
if(search(j,query))
res[cnt++] = j;
//更换输出格式
for(int j = 0;j<cnt;j++)
if(j!=cnt-1) printf("%d ",res[j]);
else printf("%d",res[j]);
printf("\n");//输出一个空行
}
}
4.测试用例
2
1 youare
3 my name is
2
you
you
1
3 you you you
1
you
1
4 you a good person
1
yo
3
9 you are a good boy ha ha o yeah
13 o my god you like bleach naruto one piece and so do i
11 but i do not think you will get all the points
5
yo
s
o
all
all
5.坑点
- 需要注意数组大小的申请,一般情况下,很难得到一个**“高维数组的越界提示”**,比如说二维数组
arr[10][10],你如果用arr[5][20]依然是可以访问到值!所以一定要注意题目的数据范围大小到底需要一个什么范围的数组!千万别模棱两可。
更多推荐


所有评论(0)