ACM 第十四天
字符串:
1、KMP算法(模式串达到1e6)
模式串达到1e4直接暴力即可。
字符串哈希
字符串Hash的种类还是有很多种的,不过在信息学竞赛中只会用到一种名为“BKDR Hash”的字符串Hash算法。
2、AC自动机
模式串1e6,子串1e4,所求串长度很小,达到50。
要学会AC自动机,我们必须知道什么是Trie,也就是字典树。Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串)。
要搞懂AC自动机,先得有模式树(字典树)Trie和KMP模式匹配算法的基础知识。ac自动机其实就是一种多模匹配算法。
AC自动机算法分为3步:解题步骤:1、建立trie树 ;2、构造失败指针(fail指针);3、模式匹配过程。
hdu 2222 AC自动机 模板
具体代码;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node
{
int cnt;//是否为该单词的最后一个结点
Node *fail;//失败指针
Node *next[];//Trie中每个结点的各个节点
}*queue[];//队列,方便用BFS构造失败指针
char s[];//主字符串
char keyword[];//需要查找的单词
Node *root;//头结点
void Init(Node *root)//每个结点的初始化
{
root->cnt=;
root->fail=NULL;
for(int i=;i<;i++)
root->next[i]=NULL;
}
void Build_trie(char *keyword)//构建Trie树
{
Node *p,*q;
int i,v;
int len=strlen(keyword);
for(i=,p=root;i<len;i++)
{
v=keyword[i]-'a';
if(p->next[v]==NULL)
{
q=(struct Node *)malloc(sizeof(Node));
Init(q);
p->next[v]=q;//结点链接
}
p=p->next[v];//指针移动到下一个结点
}
p->cnt++;//单词最后一个结点cnt++,代表一个单词
}
void Build_AC_automation(Node *root)
{
int head=,tail=;//队列头、尾指针
queue[head++]=root;//先将root入队
while(head!=tail)
{
Node *p=NULL;
Node *temp=queue[tail++];//弹出队头结点
for(int i=;i<;i++)
{
if(temp->next[i]!=NULL)//找到实际存在的字符结点
{ //temp->next[i] 为该结点,temp为其父结点
if(temp==root)//若是第一层中的字符结点,则把该结点的失败指针指向root
temp->next[i]->fail=root;
else
{
//依次回溯该节点的父节点的失败指针直到某节点的next[i]与该节点相同,
//则把该节点的失败指针指向该next[i]节点;
//若回溯到 root 都没有找到,则该节点的失败指针指向 root
p=temp->fail;//将该结点的父结点的失败指针给p
while(p!=NULL)
{
if(p->next[i]!=NULL)
{
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
//让该结点的失败指针也指向root
if(p==NULL)
temp->next[i]->fail=root;
}
queue[head++]=temp->next[i];//每处理一个结点,都让该结点的所有孩子依次入队
}
}
}
}
int query(Node *root)
{ //i为主串指针,p为模式串指针
int i,v,count=;
Node *p=root;
int len=strlen(s);
for(i=;i<len;i++)
{
v=s[i]-'a';
//由失败指针回溯查找,判断s[i]是否存在于Trie树中
while(p->next[v]==NULL && p!=root)
p=p->fail;
p=p->next[v];//找到后p指针指向该结点
if(p==NULL)//若指针返回为空,则没有找到与之匹配的字符
p=root;
Node *temp=p;//匹配该结点后,沿其失败指针回溯,判断其它结点是否匹配
while(temp!=root)//匹配结束控制
{
if(temp->cnt>=)//判断该结点是否被访问
{
count+=temp->cnt;//由于cnt初始化为 0,所以只有cnt>0时才统计了单词的个数
temp->cnt=-;//标记已访问过
}
else//结点已访问,退出循环
break;
temp=temp->fail;//回溯 失败指针 继续寻找下一个满足条件的结点
}
}
return count;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
root=(struct Node *)malloc(sizeof(Node));
Init(root);
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("\n%s",keyword);
Build_trie(keyword);
}
Build_AC_automation(root);
scanf("\n%s",s);
printf("%d\n",query(root));
}
return ;
}
next数组 模板
const int N = ;
int nxt[N];
char s[];
int slen, tlen;
void get_Next()
{
int j, k;
j = ; k = -; nxt[] = -;
tlen=strlen(s);
while(j < tlen)
if(k == - || s[j] == s[k])
nxt[++j] = ++k;
else
k = nxt[k]; }
参考博客:https://blog.csdn.net/liu940204/article/details/51345954
ACM 第十四天的更多相关文章
- HDU 6467 简单数学题 【递推公式 && O(1)优化乘法】(广东工业大学第十四届程序设计竞赛)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6467 简单数学题 Time Limit: 4000/2000 MS (Java/Others) M ...
- HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others) M ...
- HDU 6470 Count 【矩阵快速幂】(广东工业大学第十四届程序设计竞赛 )
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6470 Count Time Limit: 6000/3000 MS (Java/Others) ...
- HDU 6464.免费送气球-动态开点-权值线段树(序列中第first小至第second小的数值之和)(感觉就是只有一个状态的主席树) (“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛)
免费送气球 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)
如约而至,Java 10 正式发布! 3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...
- 我的MYSQL学习心得(十四) 备份和恢复
我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
- 雅虎(yahoo)前端优化十四条军规
第一条.尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests ) http请求是要开销的,想办法减少请求数自然可以提高网页速度.常用的方法,合并css,js(将一个页面 ...
- Bootstrap<基础二十四> 缩略图
Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...
- Bootstrap<基础十四> 按钮下拉菜单
使用 Bootstrap class 向按钮添加下拉菜单.如需向按钮添加下拉菜单,只需要简单地在在一个 .btn-group 中放置按钮和下拉菜单即可.也可以使用 <span class=&qu ...
随机推荐
- Xcode9.2 添加iOS11.2以下旧版本模拟器
问题起源 由于手边项目需要适配到iOS7, 但是手边的测试机都被更新到最新版本,所以有些潜在的bug,更不发现不了.最近就是有个用户提出一个bug,而且是致命的,app直接闪退.app闪退,最常见的无 ...
- 【Spark】源码分析之RDD的生成及stage的切分
一.概述 Spark源码整体的逻辑(spark1.3.1): 从saveAsTextFile()方法入手 -->saveAsTextFile() --> saveAsHadoopFile ...
- Drill-On-YARN
1. Drill-On-YARN介绍 功能 启动 停止 扩容 缩容 failover 启动流程 下载drill的社区包,进行必要的配置,执行drill-on-yarn.sh start命令,启动dri ...
- 第三篇 : vi编辑器配置与基本操作
目录 一.vi编辑器的配置 二.一般模式下的常用操作 一.vi编辑器的配置 配置文件位置 #配置文件virc(vi);vimrc(vim) cd /etc/vim //配置文件有在这目录的,也有可能是 ...
- 20190121-n个人围成一圈,凡报到3的人退出圈子,最后留下的是原来第几号的那位
1. 报数问题:有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位 思路:此题主要问题在于但凡报到3的人退出圈子,而报数的号码与圈子的 ...
- 20145207 myeclipse测试
实验博客
- [Jmeter]用Jmeter做压力测试(分布式)
Jmeter 是Java应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起JAVA内存溢出错误.为了让jmeter工具提 ...
- Ubuntu 安装 搜狗输入法
1.去下载搜狗输入法安装包: https://pinyin.sogou.com/linux/ 2.安装 sudo dpkg sougou****.deb 3.去设置 参考:https://blog.c ...
- ORB-SLAM(五)KeyFrame类-最小生成树
KeyFrame中维护了一个map,保存了与当前帧共视的KeyFrame*与权重(共视MapPonits数量).对关键帧之间关系是用加权有向图来完成的,那么理解其spanning tree生成树的原理 ...
- 13、Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...