最近正在学AC自动机,按照惯例需要刷一套kuangbin的AC自动机专题巩固

在网上看过很多模板,感觉kuangbin大神的模板最为简洁,于是就选择了用kuangbin大神的模板。

AC自动机其实就是字典树和KMP的结合,然后去思考一下KMP的原理,然后就是在字典树上实现KMP

这里最重要的思想可能就是fail的思想,就像KMP一样,匹配失败后,有一个next的数组去回溯(最长公共前缀后缀)

如何理解了KMP的话,感觉这个不会很难理解,字典树是一个非常简单的东西就不用讲了吧。

HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430

这是我总结出来的AC自动机解决的第一类问题,求文本串和模式串的关系(模式串出现几次之类的问题)

我把这几题放一起写了算了,因为套路一样随便改一下就好了

Keywords Search HDU - 2222

询问有多少个模式串出现在了文本串里面。

将模式串插入Trie树中,然后直接查询就好了。

 #include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <time.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a, b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define sf(n) scanf("%d", &n)
#define sff(a, b) scanf("%d %d", &a, &b)
#define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define pf printf
#define FIN freopen("data.txt","r",stdin)
#define gcd(a, b) __gcd(a,b)
#define lowbit(x) x&-x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ; struct Aho_Corasick {
int next[][], fail[], End[];
int root, cnt; int newnode() {
for (int i = ; i < ; i++) next[cnt][i] = -;
End[cnt++] = ;
return cnt - ;
} void init() {
cnt = ;
root = newnode();
} void insert(char buf[]) {
int len = strlen(buf);
int now = root;
for (int i = ; i < len; i++) {
if (next[now][buf[i] - 'a'] == -) next[now][buf[i] - 'a'] = newnode();
now = next[now][buf[i] - 'a'];
}
End[now]++;
} void build() {
queue<int> Q;
fail[root] = root;
for (int i = ; i < ; i++)
if (next[root][i] == -) next[root][i] = root;
else {
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty()) {
int now = Q.front();
Q.pop();
for (int i = ; i < ; i++)
if (next[now][i] == -) next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
} int query(char buf[]) {
int len = strlen(buf);
int now = root;
int res = ;
for (int i = ; i < len; i++) {
now = next[now][buf[i] - 'a'];
int temp = now;
while (temp != root) {
res += End[temp];
End[temp] = ;
temp = fail[temp];
}
}
return res;
} void debug() {
for (int i = ; i < cnt; i++) {
printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
for (int j = ; j < ; j++) printf("%2d", next[i][j]);
printf("]\n");
}
}
}ac; char buf[];
int T,n;
int main() {
sf(T);
while(T--){
sf(n);
ac.init();
for (int i = ; i < n; ++i) {
scanf("%s",buf);
ac.insert(buf);
}
scanf("%s",buf);
ac.build();
printf("%d\n",ac.query(buf));
}
return ;
}

病毒侵袭 HDU - 2896

给出n个模式串,对m个串进行匹配,输出匹配的模式串的编号,以及总共多少个串可以匹配。

字符总数有128,而且编号要排序。

 #include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <time.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a, b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define sf(n) scanf("%d", &n)
#define sff(a, b) scanf("%d %d", &a, &b)
#define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define pf printf
#define FIN freopen("../date.txt","r",stdin)
#define gcd(a, b) __gcd(a,b)
#define lowbit(x) x&-x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ; struct Aho_Corasick {
int next[][], fail[], End[],vis[];
int root, cnt;
vector<int>ans;
int newnode() {
for (int i = ; i < ; i++) next[cnt][i] = -;
End[cnt++] = ;
return cnt - ;
} void init() {
cnt = ;
root = newnode();
} void insert(char buf[],int id) {
int len = strlen(buf);
int now = root;
for (int i = ; i < len; i++) {
if (next[now][buf[i]] == -) next[now][buf[i]] = newnode();
now = next[now][buf[i]];
}
End[now]++;
vis[now]=id;
} void build() {
queue<int> Q;
fail[root] = root;
for (int i = ; i < ; i++)
if (next[root][i] == -) next[root][i] = root;
else {
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty()) {
int now = Q.front();
Q.pop();
for (int i = ; i < ; i++)
if (next[now][i] == -) next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
} int query(char buf[]) {
int len = strlen(buf);
int now = root;
int res = ;
for (int i = ; i < len; i++) {
now = next[now][buf[i]];
int temp = now;
while (temp != root) {
res += End[temp];
if (vis[temp]) ans.push_back(vis[temp]);
// End[temp] = 0;
temp = fail[temp];
}
}
return res;
}
void pf_ans(){
sort(ans.begin(),ans.end());
for (int i= ;i<ans.size() ;i++) printf(" %d",ans[i]);
printf("\n");
ans.clear();
}
void debug() {
for (int i = ; i < cnt; i++) {
printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
for (int j = ; j < ; j++) printf("%2d", next[i][j]);
printf("]\n");
}
}
}ac; char buf[];
int n,m;
int main() {
// FIN;
while(~sf(n)){
ac.init();
for (int i = ; i <= n; ++i) {
scanf("%s",buf);
ac.insert(buf,i);
}
ac.build();
sf(m);
int tot=;
for (int i = ; i <= m; ++i) {
scanf("%s",buf);
//fuck(i);
if (ac.query(buf)) {
tot++;
printf("web %d:",i);
ac.pf_ans();
}
}
printf("total: %d\n",tot);
}
return ;
}

病毒侵袭持续中 HDU - 3065

这题题意和上一题一样,多了一个输出出现次数。

 #include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <time.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a, b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define sf(n) scanf("%d", &n)
#define sff(a, b) scanf("%d %d", &a, &b)
#define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define pf printf
#define FIN freopen("../date.txt","r",stdin)
#define gcd(a, b) __gcd(a,b)
#define lowbit(x) x&-x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ; char str[][];
char buf[];
int n, m;
struct Aho_Corasick {
int next[*][], fail[*], End[*], num[];
int root, cnt; int newnode() {
for (int i = ; i < ; i++) next[cnt][i] = -;
End[cnt++] = ;
return cnt - ;
} void init() {
cnt = ;
root = newnode();
} void insert(char buf[], int id) {
int len = strlen(buf);
int now = root;
for (int i = ; i < len; i++) {
if (next[now][buf[i]] == -) next[now][buf[i]] = newnode();
now = next[now][buf[i]];
}
End[now] = id;
} void build() {
queue<int> Q;
fail[root] = root;
for (int i = ; i < ; i++)
if (next[root][i] == -) next[root][i] = root;
else {
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty()) {
int now = Q.front();
Q.pop();
for (int i = ; i < ; i++)
if (next[now][i] == -) next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
} void query(char buf[]) {
for(int i = ;i <= n;i++) num[i] = ;
int len = strlen(buf);
int now = root;
for (int i = ; i < len; i++) {
now = next[now][buf[i]];
int temp = now;
while (temp != root) {
if (End[temp]) num[End[temp]]++;
// End[temp] = 0;
temp = fail[temp];
}
}
for (int i= ;i<=n ;i++)
if (num[i]) printf("%s: %d\n",str[i],num[i]);
} void debug() {
for (int i = ; i < cnt; i++) {
printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
for (int j = ; j < ; j++) printf("%2d", next[i][j]);
printf("]\n");
}
}
} ac; int main() {
//FIN;
while (~sf(n)) {
ac.init();
for (int i = ; i <= n; ++i) {
scanf("%s", str[i]);
ac.insert(str[i], i);
}
ac.build();
scanf("%s", buf);
ac.query(buf);
}
return ;
}

Detect the Virus ZOJ - 3430

这题本质上还是和上面一个套路只是恶心了很多。

题目是给先你n组经过编码后的病毒串:

编码就是将原串转成二进制后取每6位进行转化成10进制后与上面表格对应的字符串,

末尾不足6位补0,且原串个数为3k+1则在编码后的串里增加'==',

若个数为3k+2则增加'=',给定的模式串也是编码后的串,

所以需要进行反编码然后就是赤裸裸的AC自动机模版了。

注意转化后的字符范围为256(包括转义字符),strlen也无法使用,需要用unsigned char

 #include <cstdio>
#include <cstring>
#include <queue> #define sf(n) scanf("%d", &n)
#define sff(a, b) scanf("%d %d", &a, &b) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ; unsigned char buf[];
char str[];
unsigned char s[];
int n, m, tot; struct Aho_Corasick {
int next[ * ][], fail[ * ], End[ * ], vis[];
int root, cnt; int newnode() {
for (int i = ; i < ; i++) next[cnt][i] = -;
End[cnt++] = ;
return cnt - ;
} void init() {
cnt = ;
root = newnode();
} void insert(unsigned char buf[], int len, int id) {
int now = root;
for (int i = ; i < len; i++) {
if (next[now][buf[i]] == -) next[now][buf[i]] = newnode();
now = next[now][buf[i]];
}
End[now] = id;
} void build() {
queue<int> Q;
fail[root] = root;
for (int i = ; i < ; i++)
if (next[root][i] == -) next[root][i] = root;
else {
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty()) {
int now = Q.front();
Q.pop();
for (int i = ; i < ; i++)
if (next[now][i] == -) next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
} int query(unsigned char buf[], int len, int n) {
memset(vis, false, sizeof(vis));
int now = root;
for (int i = ; i < len; i++) {
now = next[now][buf[i]];
int temp = now;
while (temp != root) {
if (End[temp] != -)
vis[End[temp]] = true;
temp = fail[temp];
}
}
int res = ;
for (int i = ; i <= n; i++) if (vis[i]) res++;
return res;
} void debug() {
for (int i = ; i < cnt; i++) {
printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
for (int j = ; j < ; j++) printf("%2d", next[i][j]);
printf("]\n");
}
}
} ac; unsigned char Get(char ch) {
if (ch >= 'A' && ch <= 'Z')return ch - 'A';
if (ch >= 'a' && ch <= 'z')return ch - 'a' + ;
if (ch >= '' && ch <= '')return ch - '' + ;
if (ch == '+')return ;
else return ;
} void change(unsigned char str[], int len) {
int t = ;
for (int i = ; i < len; i += ) {
buf[t++] = ((str[i] << ) | (str[i + ] >> ));
if (i + < len)
buf[t++] = ((str[i + ] << ) | (str[i + ] >> ));
if (i + < len)
buf[t++] = ((str[i + ] << ) | str[i + ]);
}
tot = t;
} int main() {
while (~sf(n)) {
ac.init();
for (int i = ; i <= n; ++i) {
scanf("%s", str);
int len = strlen(str);
while (str[len - ] == '=')len--;
for (int j = ; j < len; j++) s[j] = Get(str[j]);
change(s, len);
ac.insert(buf, tot, i);
}
ac.build();
sf(m);
for (int i = ; i <= m; i++) {
scanf("%s", str);
int len = strlen(str);
while (str[len - ] == '=') len--;
for (int j = ; j < len; j++) s[j] = Get(str[j]);
change(s, len);
printf("%d\n", ac.query(buf, tot, n));
}
printf("\n");
}
return ;
}

HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430 AC自动机求文本串和模式串信息(模板题)的更多相关文章

  1. Detect the Virus ZOJ - 3430 AC自动机

    One day, Nobita found that his computer is extremely slow. After several hours' work, he finally fou ...

  2. ZOJ - 3430 ac自动机

    这题主要就是解码过程很恶心,不能用char存,一共wa了20发 题意:先给n串加密后的字符,然后m串加密后的字符,解码之后求n对应每个m的匹配数,很显然的ac自动机 加密过程是先用对应ascii表的标 ...

  3. hdu 3695:Computer Virus on Planet Pandora(AC自动机,入门题)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

  4. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. HDU 2846 (AC自动机+多文本匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 题目大意:有多个文本,多个模式串.问每个模式串中,有多少个文本?(匹配可重复) 解题思路: 传统 ...

  6. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意: 给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数. 思路: 如果做过poj2778 ...

  7. HDU 6138 Fleet of the Eternal Throne(AC自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6138 [题目大意] 给出一些串,询问第x个串和第y个串的公共子串, 同时要求该公共子串为某个串的前 ...

  8. HDU 2896:病毒侵袭(AC自动机)

    http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:中文题意. 思路:AC自动机模板题.主要在于字符有128种,输出还要排序和去重! 注意是“total ...

  9. HDU 3695 Computer Virus on Planet Pandora(AC自动机模版题)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

随机推荐

  1. delphi xe10 中使用剪贴板(跨平台)

    VCL 中如何使用剪贴板咱就不说了,FMX 做为一个新的框架,提供了跨平台的剪贴板支持.FMX 对剪贴板的支持来自两个接口: IFMXClipboardService:位于 FMX.Platform. ...

  2. NX二次开发-UFUN关闭STL文件函数UF_STD_close_stl_file

    NX9+VS2012 #include <uf.h> #include <uf_obj.h> #include <uf_modl.h> #include <u ...

  3. 简单HOOK SSDT实现文件防删除

    http://www.rosoo.net/a/201001/8347.html

  4. Vue.js中的图片引用路径问题

    当我们在Vue.js项目中引用图片时,关于图片路径有以下几种情形: 使用一: 在data里面定义好图片路径: /*错误写法*/ imgUrl:'../assets/logo.png' 在templat ...

  5. Android 7.0 IMS框架详解

    本文主要讲解IP Multimedia Subsystem (IMS)在Android 7.0上由谷歌Android实现的部分内容.从APP侧一直到Telephony Framework,是不区分CS ...

  6. spring boot 项目打成war,丢入tomcat独立运行

    小插曲:通过cmd运行startup.bat,cmd界面显示乱码 解决方法:进入tomcat目录,conf文件夹,用编辑器打开logging.properties 将java.util.logging ...

  7. <后端>Flask框架

    1.Flask框架安装 简介:轻量级WEB框架,类似于简单版本的Django pip install flask 环境文件生成 pip freeze > requirement.txt 环境文件 ...

  8. ARM多核处理器启动过程分析

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qianlong4526888/article/details/27695173 说明: 该流程图依照 ...

  9. 转载:ASP.NET Core 在 JSON 文件中配置依赖注入

    在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等)时候,都是提供了专有的接口以供使用第三方的依赖注入组件,比如我们常用的会使用 Autofac.Untiy.Stri ...

  10. arm-linux-readelf 的使用

    1. 读 elf 文件开始的文件头部 [arm@localhost gcc]$ arm­linux­readelf ­h hello ELF Header: Magic:   7f 45 4c 46 ...