AC自动机妙用
理解题意之后,很自然的想到了用AC自动机搞,结果网上一搜,全是暴搜,按照自己的思想,AC自动机搞起,果然在提交了数次之后,看到了Accept。
AC自动机需要三个步骤:
第一步:建立字典树;
第二步:为字典树建立 Fail 指针 ;
第三步:进行匹配;
#include<iostream>
#include<string>
#include<string.h>
#include<cctype>
#include<queue>
#include<stdio.h> #define max(x,y) ((x) > (y) ? (x) : (y)) using namespace std ; struct Node {
Node *next[26] ;
Node *fail ;
bool is_over ;
int len ;
}; Node* new_node() {
Node *root = new Node ;
root ->fail = NULL ;
for(int i = 0 ; i< 26 ; i++)
root->next[i] = NULL ;
root ->is_over = false ;
return root ;
} void build_tree( Node *root , char *s ) {
int len = strlen(s) ;
for(int i = 0 ; i < len ; i++) {
if(root->next[s[i] - 'a'] == NULL)
root->next[s[i] - 'a'] = new_node() ;
root = root ->next[s[i] - 'a'] ;
}
root ->is_over = true ;
root ->len = len ;
} void build_fail(Node *root) {
Node *r = root ;
queue< Node* > q ;
q.push(root) ;
while(!q.empty()) {
r = q.front() ;
q.pop() ;
Node *p = r ;
for(int i = 0 ; i < 26 ; i++) {
if(p->next[i] != NULL) {
if(p == root) {
p->next[i]->fail = root ;
q.push(p->next[i]) ;
continue ;
}
while(r->fail->next[i] == NULL && r ->fail != root)
r = r->fail ;
if(r->fail ->next[i] != NULL)
p ->next[i]->fail = r ->fail ->next[i] ;
else
p ->next[i] ->fail = root ;
q.push(p->next[i]) ;
}
}
}
} int A_C(Node *root , char *s) {
int len = strlen(s) ;
Node *r = root ;
int count = 0 ;
for(int i = 0 ; i < len ; i++) {
if(!isalpha(s[i]))
continue ;
if(r->next[s[i]-'a'] != NULL) {
r = r ->next[s[i]-'a'] ;
if(r->is_over && !(islower(s[i+1])) && !(islower(s[i - r->len])) )
count++ ;
}
else {
while(r->next[s[i]-'a'] == NULL && r != root )
r = r ->fail ;
if(r ->next[s[i] - 'a'] != NULL)
r = r ->next[s[i] - 'a'] ;
else
r = root ;
if(r->is_over && (!(isalpha(s[i+1])) ) && !(islower(s[i - r->len])) )
count++ ;
}
} return count ;
} int main() {
int n , m ;
int t = 1 ;
while(scanf("%d%d",&n,&m) == 2) {
Node *root = new_node() ;
Node *r = root ;
while(n--) {
char s[30] ;
scanf("%s",&s) ;
getchar() ;
build_tree(root,s) ;
root = r ;
}
r->fail = NULL ;
root = r ;
build_fail(r) ;
char str[30][100] ;
char str1[30][100] ;
int count[30] = {0} ;
int ma = 0 ;
for(int i = 0 ; i < m ; i++) {
gets(str[i]) ;
strcpy(str1[i],str[i]) ;
int len = strlen(str[i]) ;
for(int j = 0 ; j < len ; j++)
if(isupper(str[i][j]))
str[i][j] += 32 ;
count[i] = A_C(root,str[i]) ;
ma = max(ma,count[i]) ;
}
cout << "Excuse Set #" << t++ << endl;
for(int k = 0 ; k < m ; k++)
if(count[k] == ma)
cout << str1[k] << endl ;
cout << endl ;
}
return 0 ;
}
AC自动机妙用的更多相关文章
- AC自动机讲解
今天花了半天肝下AC自动机,总算啃下一块硬骨头,熬夜把博客赶出来.. 正如许多博客所说,AC自动机看似很难很妙,而事实上不难,但的确很妙.笼统地说,AC自动机=Trie+KMP,但是仅仅知道这个并没有 ...
- Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例
摘要: 本文主要讲述了AC自动机的基本思想和实现原理,如何构造AC自动机,着重讲解AC自动机在算法竞赛中的一些典型应用. 什么是AC自动机? 如何构造一个AC自动机? AC自动机在算法竞赛中的典型应用 ...
- AC自动机——多个kmp匹配
(并不能自动AC) 介绍: Aho-Corasick automaton,最经典的处理多个模式串的匹配问题. 是kmp和字典树的结合. 精髓与灵魂: ①利用trie处理多个模式串 ②引入fail指针. ...
- AC自动机板子题/AC自动机学习笔记!
想知道484每个萌新oier在最初知道AC自动机的时候都会理解为自动AC稽什么的,,,反正我记得我当初刚知道这个东西的时候,我以为是什么神仙东西,,,(好趴虽然确实是个对菜菜灵巧比较难理解的神仙知识点 ...
- 洛谷 P3808 【模板】AC自动机(简单版) 题解
原题链接 前置知识: 字典树.(会 \(\texttt{KMP}\) 就更好) 显然呢,本题用 字典树 和 \(\texttt{KMP}\) 无法解决问题. 所以我们发明了一个东西: \(\textt ...
- KMP,HASH,Trie,AC自动机
我做个总结算了下午看了一下AC自动机和学习我的大生物(当然是多谢鑫神了)..完了要崩.. 1 KMP 只要是学过的人都觉得比较简单吧 但是学不会的人就感觉很难了,我是那种顿悟的然后感觉非常简单的人过程 ...
- 背单词(AC自动机+线段树+dp+dfs序)
G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ...
- 【AC自动机】背单词
题意: 0 s v:添加价值为v的字符串s 1 t:查询t中含的s的权值和.(不停位置算多次) 思路: 在线AC自动机. 同学用过一个妙妙子的分块算法. 这里用二进制分组:通常用作把在线数据结构问题转 ...
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
随机推荐
- Android 检测SD卡应用
Android 检测SD卡应用 // Environment.MEDIA_MOUNTED // sd卡在手机上正常使用状态 // ...
- BZOJ 3223 Tyvj 1729 文艺平衡树(Splay)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3223 [题目大意] 给出一数列,问m次区间翻转后的结果. [题解] Splay 区间翻 ...
- org/apache/commons/pool/impl/GenericObjectPool异常的解决办法
org/apache/commons/pool/impl/GenericObjectPool异常的解决办法 webwork+spring+hibernate框架的集成, 一启动Tomcat服务器就出了 ...
- 剑指offer26 复杂链表的复制
/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : ...
- STMP发送邮件被当垃圾邮件处理的解决方法
昨天使用了.Net通过smtp发送邮件的方式发送了一封邮件到自己的QQ邮箱,但是发送成功后并没有提示邮箱收到新的邮件,而且去收件箱里面也没有新增的邮件. 这让本人觉得奇怪,所以就觉得是否被当作垃圾邮件 ...
- 保护眼睛,绿豆沙颜色的RGB值和HSL值
现在的人尤其是职场中人,每天都得花很长时间对着电脑,对眼睛的伤害很大,其实我们可以对电脑进行一个简单的设置,把窗口背景设置成绿豆沙颜色的,对眼睛的保护很有帮助的. 下面是绿豆沙颜色的RGB值和HSL值 ...
- BZOJ 1801: [Ahoi2009]chess 中国象棋( dp )
dp(i, j, k)表示考虑了前i行, 放了0个炮的有j列, 放了1个炮的有k列. 时间复杂度O(NM^2) -------------------------------------------- ...
- C学习之指针强化
char *p = (char *)malloc(100); malloc是用于分配内存的函数,它的参数为int型,表示分配多少个字节长度,其返回类型为void*,在这里用char*就是强制转化,指定 ...
- AOP 切面编程
简介 如果你很熟悉面向方面编程(AOP),你就会知道给代码增加“切面”可以使代码更清晰并且具有可维护性.但是AOP通常都依赖于第三方类库或者硬编码的.net特性来工作.虽然这些实现方式的好处大于它们的 ...
- 搭建Hadoop集群 (二)
前面的步骤请看 搭建Hadoop集群 (一) 安装Hadoop 解压安装 登录master, 下载解压hadoop 2.6.2压缩包到/home/hm/文件夹. (也可以从主机拖拽或者psftp压缩 ...