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图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
随机推荐
- MATLAB的安装与入门
最近安装了MATLAB来用,过程遇到很多问题,担心自己改天如果换电脑了就忘记一些安装问题,所以记录一个. 首先是资源问题,我在贴吧找到了好心人分享的破解资源(非常感谢好心人的资源(ง •_•)ง),然 ...
- python中解方程
from sympy import * import numpy as np from numpy import linalg # 方程中的符号 x = Symbol('x') # 计算 result ...
- php 基础 语句include和require的区别是什么?为避免多次包含同一文件,可用(?)语句代替它们?
require->require是无条件包含也就是如果一个流程里加入require,无论条件成立与否都会先执行 require include->include有返回值,而require没 ...
- 最大流dinic板子
题目: https://www.luogu.com.cn/problem/P3376 #include <bits/stdc++.h> using namespace std; ; con ...
- Windows远程“要求的函数不受支持”解决办法
解决方法: 开启组策略中远程桌面链接安全层.1.开始-运行-gpedit.msc,进入组策略编辑器:2.找到左侧边栏计算机配置-管理模板-Windows组件-远程桌面服务-远程桌面会话主机-安全项:3 ...
- 腾讯玄武实验室向(CNVD)提交了一个重大漏洞“BucketShock”
导读 11 月 21 日,在小米 IoT 安全峰会上,腾讯安全玄武实验室负责人于旸(花名:TK 教主)在演讲中透露,腾讯玄武实验室最近向国家信息安全漏洞共享平台(CNVD)提交了一个重大漏洞“Buck ...
- 使用TortoiseGit处理代码冲突
使用TortoiseGit处理代码冲突 https://www.cnblogs.com/jason-beijing/p/5718190.html 场景一 user0 有新提交 user1 没有pu ...
- Linux centos7 linux任务计划cron、chkconfig工具、systemd管理服务、unit介绍、 target介绍
一.linux任务计划cron crontab -u -e -l -r 格式;分 时 日 月 周 user command 文件/var/spool/corn/username 分范围0-59,时范 ...
- python学习 —— 使用QRCode包生成二维码
我使用的是python3,最简单的方法就是使用QRCode,如果没有安装QRCode package,那么可以使用下面命令进行安装: pip3 install QRCode 然后,测试一下: from ...
- SystemProperities
SystemProperties与Settings.System 1 使用 SystemProperties.get 如果属性名称以“ro.”开头,那么这个属性被视为只读属性.一旦设置,属性值不能改变 ...