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图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
随机推荐
- 基于FPM制作RPM软件包!
工作中有如下情况需要将文件打包rpm: 避免重复工作,将源码程序打包为rpm 使用yum发布项目,项目打包为rpm 将自己写好的程序打包为rpm,提供给用户下载 其他 以前打包rpm是一个非常复杂的一 ...
- jmeter 并发控制
1.吞吐控制器以线程组的请求sampler为控制对象, 2.事务控制器: 3.同步定时器syn timer:对某线程组下任意的sampler任意位置作用为,有序控制单个sampler的并发先sampl ...
- Spark操作MySQL,Hive并写入MySQL数据库
最近一个项目,需要操作近70亿数据进行统计分析.如果存入MySQL,很难读取如此大的数据,即使使用搜索引擎,也是非常慢.经过调研决定借助我们公司大数据平台结合Spark技术完成这么大数据量的统计分析. ...
- 【网摘】JS 或 jQuery 获取当前页面的 URL 信息
1.设置或获取对象指定的文件名或路径. window.location.pathname 2.设置或获取整个 URL 为字符串. window.location.href 3.设置或获取与 URL 关 ...
- linux磁盘空间挂载
(1)查看磁盘空间 df -hl (3)查看硬盘及分区信息 fdisk -l (4)格式化新分区 mkfs.ext3 /dev/xvdb (5)将磁盘挂载在/www/wwwroot/default目录 ...
- uniGUI之通过URL控制参数(25)
通过URL代入参数,在代码中读取,如: http://localhost:8077/?ServerPort=212&&ServerIP=192.168.31.12 procedure ...
- Win10 在 CUDA 10.1 下跑 TensorFlow 2.x
深度学习最热的两个框架是 pytorch 和 tensorflow,pytorch 最新版本是 1.3,tensorflow 最新版本为 2.0,在 win10 下 pytorch 1.3 要求的 c ...
- ssh访问ubuntu13.10
步骤: 首先确保网络连接是ok,网络连接方式"桥接“,手动配置 ip 192.168.1.9,和主机是同一网段 1.检查当前有没有安装openssh-server(已安装) 2. 安装ope ...
- Android。WebView加载UR请求使用Cookie储存User_Id记录用户是否登陆过
1.WebView初始化的时候用倒如下代码: if (Build.VERSION.SDK_INT >= 21) { CookieManager.getInstance().setAcceptTh ...
- android悬浮按钮(Floating action button)的两种实现方法
原文: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1028/1857.html 最近android中有很多新的设计规范被引入 ...