看毛片就能AC算法
KMP && ACA
KMP:
吼哇!
反正网上教程满天飞,我就不写了。
发个自己写的模板
/**
freopen("in.in", "r", stdin);
freopen("right.out", "w", stdout);
*/
//// /////////////////////////////
#include <cstdio>
#include <string>
#include <iostream>
using std::string;
const int N = ; int nex[N]; int main() {
freopen("in.in", "r", stdin);
freopen("right.out", "w", stdout);
string s, p;
std::cin >> s >> p; nex[] = ;
for(int i = , j = ; i < p.size(); i++) {
while(j && p[i] != p[j]) {
j = nex[j - ];
}
if(p[i] == p[j]) j++; /// while(j && p[i + 1] == p[j]) j = nex[j - 1];
/// 十分失败的优化,反例:
/// acccc
/// ccc
/// 001 :next
/// 可以看出能匹配两个串,但是这个优化只能算出一个来 nex[i] = j;
} for(int i = , j = ; i < s.size(); i++) {
while(j && s[i] != p[j]) {
j = nex[j - ];
}
if(s[i] == p[j]) j++;
if(j == p.size()) {
printf("%d\n", i - j + );
j = nex[j - ];
}
} for(int i = ; i < p.size(); i++) {
printf("%d ", nex[i]);
} return ;
}
KMP模板 洛谷P3375
例题:
AC自动机:
就是KMP上trie,用以解决多串匹配问题。
当我花几天的时间理解KMP之后,AC自动机也就很显然了(这怎么就显然了?)
想当我学KMP满大街找教程,现在学AC自动机教程还没看完就懂了...所以说基础很重要。
大致想象一下就行了。直接发代码吧。
#include <cstdio>
#include <string>
#include <iostream>
#include <queue>
#include <cstring>
const int N = ; using std::string; struct AC {
int root, tot;
int tr[N][], nex[N], ed[N];
bool vis[N];
AC() {
root = ;
tot = ;
}
void clear() {
for(int i = ; i <= tot; i++) {
nex[i] = ed[i] = ;
for(int j = ; j < ; j++) {
tr[i][j] = ;
}
}
return;
} inline void insert(string x) {
int p = root;
for(int i = ; i < x.size(); i++) {
int f = x[i] - 'a';
if(!tr[p][f]) {
tr[p][f] = ++tot;
}
p = tr[p][f];
}
ed[p]++;
return;
}
void getnex() {
nex[root] = root;
std::queue<int> Q;
Q.push(root);
while(!Q.empty()) {
int x = Q.front();
Q.pop();
for(int i = ; i < ; i++) {
int y = tr[x][i];
if(y) {
int j = nex[x];
while(j != root && !tr[j][i]) {
j = nex[j];
}
if(tr[j][i] && x != root) {
j = tr[j][i];
}
nex[y] = j;
Q.push(y);
}
}
}
return;
}
int solve(string x) {
int ans = ;
memset(vis, , (tot + ) * sizeof(bool));
for(int i = , j = root; i < x.size(); i++) {
int f = x[i] - 'a';
while(j != root && !tr[j][f]) {
j = nex[j];
}
if(tr[j][f]) {
j = tr[j][f];
}
if(ed[j] && !vis[j]) {
ans += ed[j];
vis[j] = ;
}
}
return ans;
}
}ac; int main() {
int n;
scanf("%d", &n);
string s;
for(int i = ; i <= n; i++) {
std::cin >> s;
ac.insert(s);
}
ac.getnex();
std::cin >> s;
printf("%d", ac.solve(s));
return ;
}
洛谷P3808
#include <cstdio>
#include <string>
#include <iostream>
#include <queue>
#include <cstring>
const int N = ; using std::string; struct Ans {
string s;
int cnt;
}a[N]; struct AC {
int root, tot;
int tr[N][], nex[N], ed[N];
AC() {
root = ;
tot = ;
}
void clear() {
for(int i = ; i <= tot; i++) {
nex[i] = ed[i] = ;
for(int j = ; j < ; j++) {
tr[i][j] = ;
}
}
tot = ;
return;
} inline void insert(string x, int k) {
int p = root;
for(int i = ; i < x.size(); i++) {
int f = x[i] - 'a';
if(!tr[p][f]) {
tr[p][f] = ++tot;
}
p = tr[p][f];
}
ed[p] = k;
return;
}
void getnex() {
nex[root] = root;
std::queue<int> Q;
Q.push(root);
while(!Q.empty()) {
int x = Q.front();
Q.pop();
for(int i = ; i < ; i++) {
int y = tr[x][i];
if(y) {
int j = nex[x];
while(j != root && !tr[j][i]) {
j = nex[j];
}
if(tr[j][i] && x != root) {
j = tr[j][i];
}
nex[y] = j;
Q.push(y);
}
}
}
return;
}
void solve(string x) {
for(int i = , j = root; i < x.size(); i++) {
int f = x[i] - 'a';
while(j != root && !tr[j][f]) {
j = nex[j];
}
if(tr[j][f]) {
j = tr[j][f];
}
int jj = j;
while(jj != root) {
if(ed[jj]) {
a[ed[jj]].cnt++;
}
jj = nex[jj];
}
}
return;
}
}ac; int main() {
int n;
string x;
while(scanf("%d", &n) && n) {
ac.clear();
for(int i = ; i <= n; i++) {
std::cin >> a[i].s;
ac.insert(a[i].s, i);
}
ac.getnex();
std::cin >> x;
ac.solve(x);
int large = -;
for(int i = ; i <= n; i++) {
large = std::max(large, a[i].cnt);
}
printf("%d\n", large);
for(int i = ; i <= n; i++) {
if(a[i].cnt == large) {
std::cout << a[i].s << std::endl;
}
}
for(int i = ; i <= n; i++) {
a[i].cnt = ;
}
}
return ;
}
洛谷P3796
重点在于getnex()函数。别的依题意稍作修改即可。
第二题有个优化:ed[nex[jj]]可能为0,会额外增加跳的次数。解决办法是搞一个g数组出来表示ed[]不为0的某个nex。
被之前失败的优化经历搞怕了,没用...
KMP与AC自动机的小差异:(在我的模板中)
KMP初始化的nex[0] = 0,而AC自动机的初始化nex[root] = root;
KMP中的nex[i]表示最长匹配数,是比下标多1的,而AC自动机中直接指向一个节点。
看毛片就能AC算法的更多相关文章
- kmp//呵呵!看毛片算法
以前刚学的时候迷迷糊糊的,一看就懵圈,前几天捡起来的时候 发现还不会 于是研究了两天,自尊心严重受挫,今天的时候 突然一道灵光迸发,居然 感觉好像懂了,于是又琢磨起来 终于 我懂了 呵呵! ...
- KMP算法再解 (看毛片算法真是人如其名,哦不,法如其名。)
KMP算法主要解决字符串匹配问题,其中失配数组next很关键: 看毛片算法真是人如其名,哦不,法如其名. 看了这篇博客,转载过来看一波: 原博客地址:https://blog.csdn.net/sta ...
- SDUT OJ 数据结构实验之串一:KMP简单应用 && 浅谈对看毛片算法的理解
数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...
- 快速字符串匹配一: 看毛片算法(KMP)
前言 由于需要做一个快速匹配敏感关键词的服务,为了提供一个高效,准确,低能耗的关键词匹配服务,我进行了漫长的探索.这里把过程记录成系列博客,供大家参考. 在一开始,接收到快速敏感词匹配时,我就想到了 ...
- AC算法学习笔记
1.算法流程图 (1) void Init() 此函数是初始化函数,用来给fail数组和goto数组初始化值. (2) void GotoFunction(string x) 这个函数的作 ...
- [转] 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽
字符串模式匹配算法——BM.Horspool.Sunday.KMP.KR.AC算法一网打尽 转载自:http://dsqiu.iteye.com/blog/1700312 本文内容框架: §1 Boy ...
- 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽
字符串模式匹配算法——BM.Horspool.Sunday.KMP.KR.AC算法一网打尽 本文内容框架: §1 Boyer-Moore算法 §2 Horspool算法 §3 Sunday算法 §4 ...
- 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法
ref : https://dsqiu.iteye.com/blog/1700312 本文内容框架: §1 Boyer-Moore算法 §2 Horspool算法 §3 Sunday算法 §4 KMP ...
- AC算法 及python实现
零 导言 软件安全课上,老师讲了AC算法,写个博客,记一下吧. 那么AC算法是干啥的呢? ——是为了解决多模式匹配问题.换句话说,就是在大字符串S中,看看小字符串s1, s2,...有没有出现. AC ...
随机推荐
- linux下编译opencv
1.安装cmake:sudo apt-get install cmake 2.下载opencv-2.4.10.zip,解压 3.编译opencv cd /home/opencv-2.4.10 mkdi ...
- asp.net core 2.1 部署IIS(win10/win7)
asp.net core 2.1 部署IIS(win10/win7) 概述 与ASP.NET时代不同,ASP.NET Core不再是由IIS工作进程(w3wp.exe)托管,而是使用自托管Web服务器 ...
- 通过Visual Studio 2012 比较SQL Server 数据库的架构变更
一 需求 随着公司业务的发展,数据库实例也逐渐增多,数据库也会越来越多,有时候我们会发现正式生产数据库也测试数据库数据不一致,也有可能是预发布环境下的数据库与其他数据库架构不一致,或者,分布式数据库上 ...
- python——python3.6环境搭建(Windows10,64位)
1.python软件资源下载 1.1 打开python官网地址:https://www.python.org 1.2 根据自己电脑的设置选择下载合适的python3.6.2 1.3 此处选择windo ...
- yum源 Python3 Django mysql安装
yum 源安装 yum源位置: yum源仓库的地址 在/etc/yum.repos.d/,并且只能读出第一层的repo文件 yum仓库的文件都是以.repo结尾的 linux软件包管理 yum工具如同 ...
- 多节点,多线程下发订单,使用zookeeper分布式锁机制保证订单正确接入oms系统
假设订单下发, 采用单机每分钟从订单OrderEntry接口表中抓100单, 接入订单oms系统中. 由于双十一期间, 订单量激增, 导致订单单机每分钟100单造成, 订单积压. 所以采用多节点多线程 ...
- MySql数据库在NodeJS中简单的基本操作
阅读目录 一:连接数据库 二:数据的增删改查操作 2.1 数据库新增和查询数据 2.2 获取该数据的主键值 2.3 多语句查询 回到顶部 一:连接数据库 const mysql = require(' ...
- .net core2.1 三层中使用Autofac代替原来Ioc
首先,现有的三层项目的结构 其中 Repository public interface IPersonRepository { string Eat(); } public class Perso ...
- 【原创】讲讲亿级PV的负载均衡架构
引言 本来没想写这个题材的,为了某某童鞋能够更好的茁壮成长,临时写一篇负载均衡的.负载均衡,大家可能听过什么3层负载均衡.4层负载均衡.7层负载均衡什么的?那这是怎么分的呢,ok,是根据osi七层网络 ...
- 程序员买房指南——LZ的三次买房和一次卖房经历
引言 买房,一直是程序员群体绕不开的一个话题,尤其是到了一定年纪和人生阶段以后,买房这件事会变得越来越迫切. 为什么LZ一上来就说,买房是程序员绕不开的一个话题? 其实原因很简单,由于程序员这个职业的 ...