看毛片就能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 ...
随机推荐
- Android studio,第一个生成,调用成功的jni(说多了都是泪)
0x01 序言: 泪从何处说起呢?其实很早以前就用过android studio写过c++,但是,但是一直没有成功生成过so文件,所以心中一直有一个纠结...为什么不成功呢... 直到今天,由于工作的 ...
- 一文把samba相关的都说清楚
1.前言 samba源码都一样,配置也也一样,各个不同linux版本,唯一不同的是对服务的启动方式不同.下面以ubuntu14.4为例,说明. 2. 安装samba samba的安装,可以源码安装,大 ...
- EntityFramework Code-First 简易教程(六)-------领域类配置之DataAnnotations
EF Code-First提供了一个可以用在领域类或其属性上的DataAnnotation特性集合,DataAnnotation特性会覆盖默认的EF约定. DataAnnotation存在于两个命名空 ...
- AngularJS学习之旅—AngularJS Table(十一)
1.AngularJS 表格 1. ng-repeat 指令可以完美的显示表格 AngularJS 实例 <!DOCTYPE html> <html> <head> ...
- 【原】Java学习笔记008 - 方法(函数)
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 方法/函数 Met ...
- linux缺页异常处理--内核空间
缺页异常被触发通常有两种情况-- 程序设计的不当导致访问了非法的地址 访问的地址是合法的,但是该地址还未分配物理页框. 下面解释一下第二种情况,这是虚拟内存管理的一个特性.尽管每个进程独立拥有3GB的 ...
- Jenkins自动化部署-----持续交付【转】
感谢之前带领过我的leader,让我能够知道什么是好的开发方法. 在很早之前就接触过敏捷开发.什么是敏捷开发,简单来说就是让软件可靠地,快速地发布出来的一种开发方法和技巧. 而敏捷开发中有许多的实践, ...
- c/c++ 多线程 std::call_once的应用
多线程 std::call_once的应用 std::call_once的应用:类成员的延迟初始化,并只初始化一次.和static的作用很像,都要求是线程安全的,c++11之前在多线程的环境下,sta ...
- JMeter测试工具的使用
Jmeter下载地址: http://jmeter.apache.org/download_jmeter.cgi 解压Jmeter压缩包,双击jmeter.bat 右击测试计划 右击线程组 右击HTT ...
- solr 7.7 搭建和搜索
最近做了个solr搜索的demo, 用的是solr7.7,之前网上好多文章搭建solr都是5.5+tomcat.. 自己摆弄了下,发现solr7.7和5.5 的部分文件夹有些改动,没有深究原理也就没有 ...