看毛片就能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 ...
随机推荐
- ext图片预览功能实现,前端代码
效果图: extjs代码: // 模型 Ext.define('ParkingAttachment', {extend: "Ext.data.Model", idProperty: ...
- Word Count作业
Word Count作业 一.个人Gitee地址:https://gitee.com/Changyu-Guo 二.项目简介 该项目主要是模拟Linux上面的wc命令,基本要求如下: 命令格式: wc. ...
- Asp.net mvc 项目返回Json
因mvc控制器返回类型JsonResult 在处理对象转JSON的时候,对日期的格式化处理并不太符合要求,所以重新继承抽象类ActionResult使用Newtonsoft.Json来系列化 usin ...
- sql server 错误日志errorlog
一 .概述 SQL Server 将某些系统事件和用户定义事件记录到 SQL Server 错误日志和 Microsoft Windows 应用程序日志中. 这两种日志都会自动给所有记录事件加上时间戳 ...
- linux Page cache和buffer cache正解
Page cache和buffer cache一直以来是两个比较容易混淆的概念,在网上也有很多人在争辩和猜想这两个cache到底有什么区别,讨论到最后也一直没有一个统一和正确的结论,在我工作的这一段时 ...
- Django学习开发--笔记一(从零开始)
创建django项目注: 首先需在python中下载django 命令:pip install django1.任意文件中创建django项目 diango-admin startproject my ...
- 合并两个有序链表的golang实现
将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 输入:->->, ->-> 输出:->->->->-> ...
- Maven的简单使用
Maven使用 在官网下载maven: http://maven.apache.org/download.cgi 解压到D盘(位置随便) 配置环境变量 打开dos窗口,检测是否成功,出现如下画面表示配 ...
- Django组件--分页器(有用)
一.分页器对象 from django.core.paginator import Paginator,EmptyPage book_list = Book.objects.all() #假设有100 ...
- 日志学习系列(一)——Log4net的基础知识学习
今天把Log4net日志记录做了封装,作为一个公共的类库.记录一下应该注意的地方.先了解一下log4net的理论知识. 参考百度百科 一.log4net是什么? log4net库是Apache log ...