HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430 AC自动机求文本串和模式串信息(模板题)
最近正在学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自动机求文本串和模式串信息(模板题)的更多相关文章
- Detect the Virus ZOJ - 3430 AC自动机
One day, Nobita found that his computer is extremely slow. After several hours' work, he finally fou ...
- ZOJ - 3430 ac自动机
这题主要就是解码过程很恶心,不能用char存,一共wa了20发 题意:先给n串加密后的字符,然后m串加密后的字符,解码之后求n对应每个m的匹配数,很显然的ac自动机 加密过程是先用对应ascii表的标 ...
- hdu 3695:Computer Virus on Planet Pandora(AC自动机,入门题)
Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 256000/1280 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 2846 (AC自动机+多文本匹配)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 题目大意:有多个文本,多个模式串.问每个模式串中,有多少个文本?(匹配可重复) 解题思路: 传统 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意: 给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数. 思路: 如果做过poj2778 ...
- HDU 6138 Fleet of the Eternal Throne(AC自动机)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6138 [题目大意] 给出一些串,询问第x个串和第y个串的公共子串, 同时要求该公共子串为某个串的前 ...
- HDU 2896:病毒侵袭(AC自动机)
http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:中文题意. 思路:AC自动机模板题.主要在于字符有128种,输出还要排序和去重! 注意是“total ...
- HDU 3695 Computer Virus on Planet Pandora(AC自动机模版题)
Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 256000/1280 ...
随机推荐
- Jmeter-【JSON Extractor】-响应结果中三级key取值
一.请求返回样式 二.取第三个option 三.查看结果
- Android 防止切换横屏闪退
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...
- 二分图染色+分组背包+bitset优化——hdu5313
首先就是求联通块,每个联通块里记录两个部分的元素个数 目标是使一边的体积接近n/2 那么每个联通块作为一组,进行分组背包,dp[i]表示体积i是否可以被凑出来,可行性背包是可以用bitset优化的 最 ...
- lua数据类型与变量
Lua数据类型与变量 Lua中有 8个基本类型分别为: nil.boolean.number.string.userdata.function.thread和 table. lua变量三种类型:全局 ...
- 2019年12月12日英语学习-Will I Or Won't I ?
这节英语课上的内容没记住多少东西,觉得这个主题太枯燥了,不过整堂课和外教沟通交流还是不错的,因为这节课就我一个学生.给我了充分的机会去张嘴交流互动. 也没记住什么东西,不知道写什么.只记住将要决定做某 ...
- (转) mysql的分区技术 .
转:http://blog.csdn.net/feihong247/article/details/8100960 一.概述 当 MySQL的总记录数超过了100万后,会出现性能的大幅度下降吗?答案是 ...
- docker网络原理
以下内容引用Docker -- 从入门到实践 当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机.它会在挂 ...
- spark-sql性能优化之——多线程实现多Job并发执行
直接上代码 val spark = SparkSession.builder() .appName("name") .master("local[2]") .g ...
- Apache Spark 2.2.0 中文文档 - Spark RDD(Resilient Distributed Datasets)
Spark RDD(Resilient Distributed Datasets)论文 概要 1: 介绍 2: Resilient Distributed Datasets(RDDs) 2.1 RDD ...
- c++11 Thread库写多线程程序
一个简单的使用线程的Demo c++11提供了一个新的头文件<thread>提供了对线程函数的支持的声明(其他数据保护相关的声明放在其他的头文件中,暂时先从thread头文件入手吧),写一 ...