看毛片就能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 ...
随机推荐
- 在Windows 10上利用seafile搭建个人云服务
参考seafile官方文档 安装Python 2.7.11 32位版 下载地址:https://www.python.org/downloads/release/python-2711/ 选择 32位 ...
- win快捷键
******************键盘快捷键大全****************** 一.常见用法: F1 显示当前程序或者windows的帮助内容. F2 当你选中一个文件的话,这意味着“重命名 ...
- AjaxPro2完整入门教程
一.目录 简单类型数据传送(介绍缓存,访问Session等) 表类型数据传送 数组类型数据传送(包含自定义类型数据) 二.环境搭建 1.这里本人用的是VS2012. 2.新建一个空的Web项目(.NE ...
- php二维数组根据某个字段去重
php的二维数组根据某个字段去重,在这默认为二维数组的结构是一样的,现在根据二维数组里的id字段去重,把id相同的重复的元素去掉 /** * 二维数组根据某个字段去重 * @param array $ ...
- c++中 . 和 -> 的区别是什么?
主要用于访问类的成员,->主要用于类类型的指针访问类的成员,而.运算符,主要用于类类型的对象访问类的成员. 例如: class A { public :int a } A ma; A *p=&a ...
- Redis管道和发布订阅
管道:原子性执行命令 ''' redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作, 如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定 ...
- css设置文字上下居中,一行文字居中,两行或多行文字同样居中。
转:https://www.cnblogs.com/handsomeBoys/p/6599062.html HTML: <div class="book-detail-store-it ...
- sql server 压缩数据库
收缩日志 ALTER DATABASE 数据库名称 SET RECOVERY SIMPLEDBCC SHRINKDATABASE(数据库名称, 0) 压缩数据库ALTER DATABASE 数据库名称 ...
- PHP性能优化:in_array和isset 在大数组查询中耗时相差巨大,以及巧妙使用array_flip
今天在PHP业务开发中,发现了一个问题. 两个较大数组(20万+元素),遍历其中一个$a,另一个数组$b用于查找元素. 比如 foreach($a as $val){ if(in_array($xx, ...
- L2-2 小字辈 (25 分)
本题给定一个庞大家族的家谱,要请你给出最小一辈的名单. 输入格式: 输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号.随后第二行 ...