HihoCoder第四周:Trie图
第四周的题目是前两周的综合,综合在一个是KMP算法的思想,一个是树的这么一个数据结构。
题目 : Trie图
输入
每个输入文件有且仅有一组测试数据。
每个测试数据的第一行为一个整数N,表示河蟹词典的大小。
接下来的N行,每一行为一个由小写英文字母组成的河蟹词语。
接下来的一行,为一篇长度不超过M,由小写英文字母组成的文章。
对于60%的数据,所有河蟹词语的长度总和小于10, M<=10
对于80%的数据,所有河蟹词语的长度总和小于10^3, M<=10^3
对于100%的数据,所有河蟹词语的长度总和小于10^6, M<=10^6, N<=1000
输出
对于每组测试数据,输出一行"YES"或者"NO",表示文章中是否含有河蟹词语。
样例输入
6
aaabc
aaac
abcc
ac
bcd
cd
aaaaaaaaaaabaaadaaac
样例输出
YES
一开始我的思路是对每一个节点,每一个struct立面定义一个suffix指针,代表它的后缀节点,但是因为题目要不断地查找后缀节点,这样指针觉得麻烦,所以直接定义一个node[1000005],因为题目中已经说了最多的词语长度就是10^6。
不多说,直接上代码,代码中细说。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std; #define len 1000000 char s[1000006];
char dir[1000006]; int node_count=0;//节点总数 struct Node {
int flag;//是否结束
int suffix;//node[p].suffix的值就直接代表它的后缀节点
int next[26];//这里的next是为构建树所用,即node[p].next['a']就代表当前节点经过字符'a'跳到哪一个节点中去
}node[len]; void init()
{
int count;
for(count =0;count<len;count++)
{
node[count].flag = 0;
node[count].suffix = 0;
for(int i=0;i<26;i++)
node[count].next[i]= 0;
}
} void Add_Trie(char *f_s)
{
int len_s = strlen(f_s);
int p=0,i; for(i=0;f_s[i];i++)
{
if(!node[p].next[f_s[i]-'a'] )
{
node[p].next[f_s[i]-'a']= ++node_count;
} p=node[p].next[f_s[i]-'a'];
}
node[p].flag = 1; } void Cal_Suffix()
{
queue<int> q;
/*这个队列我没想到,是看到其他人的代码才想到的
一开始我是循环了所有节点,结果就是处理的很乱,
有的处理了两遍。所以,实际上用queue的好处在于
能理清思路,这个节点进入队列,开始计算这个节点
后缀节点,顿时思路很清晰明了了。
其实后缀节点只是为了计算next[]数组时所用的工具。
因为next数组在树中一开始只是记录真正经过的节点,
现在要通过next数组来计算如果这时字符串与字典不
匹配的话,要跳到哪里去,实际上感觉这像是自动机
的内容*/
int p, i;
q.push(0);
while(!q.empty())
{
p = q.front();
q.pop(); if(node[node[p].suffix].flag ==1)
node[p].flag = 1;
for(i = 0; i < 26; i++)
if(node[p].next[i])//如果该节点有下一个节点
{
q.push(node[p].next[i]);//就把它放入到队列中
if(p)
node[node[p].next[i]].suffix = node[node[p].suffix].next[i];//如果不是起始节点,那么当前节点P的经过字符i下一个节点的后缀节点是P的后缀节点经过字符i后的节点
}
else
node[p].next[i] = node[node[p].suffix].next[i];//如果没有下一个节点,那么这时suffix发威了,就跳到当前节点P的后缀节点经过字符i的节点上去
}
} bool Search(char *f_s)
{
int len_f_s = strlen(f_s);
int count1=0,p=0; while(f_s[count1])
{
p=node[p].next[f_s[count1] - 'a'];
if(node[p].flag == 1)
{
return true;
}
count1++;
}
return false;
}
int main()
{
init(); int dir_count;
cin>>dir_count; while(dir_count--)
{
cin>>s;
Add_Trie(s);//添加到树种
} Cal_Suffix();//计算每个节点的后缀节点 cin>>dir;
if(Search(dir))//计算结果
cout<<"YES"<<endl;
else
cout<<"NO"<<endl; return 0;
}
整个程序第一点感受就是赋初值别乱赋,想清楚了在开始,一开始的suffix,next数组初值设置为-1,殊不知,可能那里一个取值(数组[-1]),程序就出错了。
第二点感受在memset函数的使用上,以后memset除了0,除了char型数组,用的话要小心谨慎。
第三点感受就是这道题看着复杂,但人家都有hint了。。。理清思路的话,不是很难。
最后一点感受就是 好像是拖得越久,记得越深。。。现在每次做题都能把焦点从算法转移到某一个函数用法或是数据结构上去,说明自己基础还是远远不够。STL中的vector、queue、list等 ,只是知道了其用法,根本没有完全掌握。
下次再编代码之前,要首先理清思路,设计好整个程序的数据结构,各个函数的用法,再去实现其具体功能,比现在这样上来就编然后就提交,再然后就是WA,再去找bug,改得最后面目全非的,思路逻辑混乱,几乎就是看正确答案才能编出来的这幅德行好多了。
版权声明:本文为博主原创文章,未经博主允许不得转载。
HihoCoder第四周:Trie图的更多相关文章
- 【hihoCoder】1036 Trie图
题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...
- 【hihoCoder 1036】Trie图
看了一下简单的$Trie图$,调模板调啊调一连调了$2h$,最后发现$-'a'$打成$-'A'$了hhh,有种摔键盘的冲动. $Trie图$是$Trie树$上建立“前缀边”,不用再像在$Trie树$上 ...
- hiho一下 第二周&第四周:从Trie树到Trie图
hihocoder #1014 题目地址:http://hihocoder.com/problemset/problem/1014 hihocoder #1036 题目地址: http://hihoc ...
- hihoCoder#1036 Trie图
原题地址 看了这篇博文,总算是把Trie图弄明白了 Runtime Error了无数次,一直不知道为什么,于是写了个脚本生成了一组大数据,发现果然段错误了. 调试了一下午,总算闹明白了,为什么呢? 1 ...
- Trie 图
时间限制:20000ms 单点时限:1000ms 内存限制:512MB 描述 前情回顾 上回说到,小Hi和小Ho接受到了河蟹先生伟大而光荣的任务:河蟹先生将要给与他们一篇从互联网上收集来的文章,和一本 ...
- 【AC自动机&&Trie图】积累
以前KMP和后缀系列(主要是后缀数组,后缀自动机),都刷了一定数量的题,但是对于AC自动机,却有些冷落,罪过. 但是我感觉,在蓝桥杯比赛中AC自动机出现的概率比后缀系列大,简单的会考匹配,稍难一点会考 ...
- 小菜鸟 菜谈 KMP->字典树->AC自动机->trie 图 (改进与不改进)
本文的主要宗旨是总结自己看了大佬们对AC自动机和trie 图 的一些理解与看法.(前沿:本人水平有限,总结有误,希望大佬们可以指出) KMP分割线--------------------------- ...
- 【BZOJ-2938】病毒 Trie图 + 拓扑排序
2938: [Poi2000]病毒 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 609 Solved: 318[Submit][Status][Di ...
- 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
随机推荐
- php学习函数如何执行的
入口栈abc(4)--------abc(4)------abc(3)-----abc(2)再返回上一层栈,执行完后返回上一层.输出$n=2-------$n=2-------$n=3
- golang的io.copy使用
net/http 下载 在golang中,如果我们要下载一个文件,最简单的就是先用http.get()方法创建一个远程的请求后,后面可使用ioutil.WriteFile()等将请求内容直接写到文件中 ...
- win8.1 virtualbox 安装centos7注意事项
win8.1是64位的,一开始在virtualbox中选择版本时,怎么也选不到64位的,这时要改BIOS设置,把CPU虚拟化改为允许. virtualbox是32位的,没必要非得是64位(64位的也不 ...
- selenium webdriver 模拟鼠标悬浮
/**模拟鼠标悬浮在某元素上 * @param driver * @param locator */ public static void moveToElement(WebDriver driver ...
- 四 Spring的工厂类,xml的配置
Spring工厂类的结构图: BeanFactory:老版本的工厂类 BeanFactory:调用getBean的时候,才会生产类的实例 ApplicationFactory:新版本的工厂类 加载配置 ...
- LeetCode中等题(二)
题目一: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...
- jquery对象和dom原生获取的对象是不同的。
写了一个点击无缝滚动的demo,但是点击的时候如果上一个不运动完成,在快速点击就会快闪. 可是开始也清除定时器了,后来发现是传入的jq对象,jqobj.timer=定时器,这里jqobj没法添加.ti ...
- (转)js实现倒计时效果(年月日时分秒)
原文链接:http://mengqing.org/archives/js-countdown.html 之前做的活动页面很多都用到了倒计时功能,所以整理下下次直接用.(用的是张鑫旭写的一个倒计时,稍作 ...
- 「JOI2019 Final」解题报告
传送门 「JOI2019 Final」勇者比太郎 看懂题就很简单了,后缀和随便维护一下就好了,别用树状数组强加一个\(\log\)就行. 「JOI2019 Final」画展 显然可以先把所有的画框按大 ...
- 本周总结(19年暑假)—— Part2
日期:2019.7.21 博客期:108 星期日 这几天正在认真学习大数据,我是在B站上看尚老师的视频搞得.我已经配好了Hadoop的基本环境,现在学习的是HDFS的相关内容