[hdu5164]ac自动机
中文题目:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=563&pid=1003
首先贴一下bc的题解:
首先我们考虑m=1的情况。给定两个数组A={a1,a2,…,an}和B={b1,b2,…,bk},问B在A中出现了几次。令ci=ai+1ai,1≤i<n,同样令di=bi+1bi,1≤i<k,那么上述问题可以转化为ci和di的模式匹配问题,这个正确性显然,也没有什么好证明的。于是对于m=1的情况只有用个kmp即可搞定。
现在考虑m>1的情况,我们考虑用ac自动机来做。考虑到字符集并不是普通的数字,而是一个分数,我们不放搞个分数类,然后用map存转移边。用m个模式串(Bob的序列)建好自动机之后,把文本串(Alice的序列)在自动机上跑一遍即可统计出答案。
事实上,这个题的精华就在于序列变换,将问题转化为多模板匹配问题。而且由于转化后的序列有二维状态,可以用map映射重新为状态分配一个值(类似离散)。另外由于字符集比较大,所以ac自动机里面需要一点小小的修改,原来的二维数组的第二维需用map,另外需要同时记录所有儿子的字符值。原来的模板只需要小改就可以适应这种情况了。详见代码:
#pragma comment(linker, "/STACK:10240000,10240000") #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <ctime>
#include <cctype>
#include <set>
#include <bitset>
#include <functional>
#include <numeric>
#include <stdexcept>
#include <utility> using namespace std; #define mem0(a) memset(a, 0, sizeof(a))
#define mem_1(a) memset(a, -1, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define define_m int m = (l + r) >> 1
#define rep_up0(a, b) for (int a = 0; a < (b); a++)
#define rep_up1(a, b) for (int a = 1; a <= (b); a++)
#define rep_down0(a, b) for (int a = b - 1; a >= 0; a--)
#define rep_down1(a, b) for (int a = b; a > 0; a--)
#define all(a) (a).begin(), (a).end()
#define lowbit(x) ((x) & (-(x)))
#define constructInt4(name, a, b, c, d) name(int a = 0, int b = 0, int c = 0, int d = 0): a(a), b(b), c(c), d(d) {}
#define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {}
#define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {}
#define pchr(a) putchar(a)
#define pstr(a) printf("%s", a)
#define sstr(a) scanf("%s", a)
#define sint(a) scanf("%d", &a)
#define sint2(a, b) scanf("%d%d", &a, &b)
#define sint3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define pint(a) printf("%d\n", a)
#define test_print1(a) cout << "var1 = " << a << endl
#define test_print2(a, b) cout << "var1 = " << a << ", var2 = " << b << endl
#define test_print3(a, b, c) cout << "var1 = " << a << ", var2 = " << b << ", var3 = " << c << endl typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi; const int dx[] = {, , -, , , , -, -};
const int dy[] = {-, , , , , -, , - };
const int maxn = 3e4 + ;
const int md = ;
const int inf = 1e9 + ;
const LL inf_L = 1e18 + ;
const double pi = acos(-1.0);
const double eps = 1e-; template<class T>T gcd(T a, T b){return b==?a:gcd(b,a%b);}
template<class T>bool max_update(T &a,const T &b){if(b>a){a = b; return true;}return false;}
template<class T>bool min_update(T &a,const T &b){if(b<a){a = b; return true;}return false;}
template<class T>T condition(bool f, T a, T b){return f?a:b;}
template<class T>void copy_arr(T a[], T b[], int n){rep_up0(i,n)a[i]=b[i];}
int make_id(int x, int y, int n) { return x * n + y; } LL ans; struct AhoCorasickAutoMata {
const static int maxn = ;
int cc;
map<int, int> ch[maxn];
vector<int> son[maxn];
int val[maxn], last[maxn], f[maxn]; void clear() { cc = ; mem0(val); mem0(ch); mem0(last); mem0(f); rep_up0(i, maxn) { son[i].clear(); ch[i].clear(); } } void Insert(int s[], int n) {
int pos = ;
rep_up0(i, n) {
int id = s[i];
if(!ch[pos][id]) {
ch[pos][id] = ++ cc;
son[pos].push_back(id);
}
pos = ch[pos][id];
}
val[pos] ++;
} void print(int j) {
if (j) {
ans += val[j];
print(last[j]);
}
} void find(int T[], int n) {
int j = ;
rep_up0(i, n) {
int c = T[i];
while (j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else {
if (last[j]) print(last[j]);
}
}
} int getFail() {
queue<int> q;
f[] = ;
int SZ = son[].size();
rep_up0(i, SZ) {
int c = son[][i];
int u = ch[][c];
q.push(u);
}
while (!q.empty()) {
int r = q.front(), SZ = son[r].size(); q.pop();
rep_up0(i, SZ) {
int c = son[r][i];
int u = ch[r][c];
q.push(u);
int v = f[r];
while (v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]]? f[u] : last[f[u]];
}
}
}
}; AhoCorasickAutoMata ac;
map<pii, int> mp;
int pa[], pb[];
int a[], b[]; int main() {
//freopen("in.txt", "r", stdin);
int T, n, m, tot = ;
cin >> T;
while (T--) {
ans = ;
ac.clear();
mp.clear();
cin >> n >> m;
rep_up0(i, n) {
sint(a[i]);
}
rep_up0(i, n - ) {
int g = gcd(a[i], a[i + ]);
int ga = a[i] / g, gb = a[i + ] / g;
int &x = mp[make_pair(ga, gb)];
if (!x) x = ++ tot;
pa[i] = x;
} rep_up0(i, m) {
int k;
sint(k);
rep_up0(j, k) {
sint(b[j]);
}
if (k > n) continue;
if (k == ) {
ans += n;
continue;
}
rep_up0(j, k - ) {
int g = gcd(b[j], b[j + ]);
int ga = b[j] / g, gb = b[j + ] / g;
int &x = mp[make_pair(ga, gb)];
if (!x) x = ++ tot;
pb[j] = x;
}
ac.Insert(pb, k - );
}
ac.getFail();
ac.find(pa, n - );
cout << ans << endl;
}
return ;
}
[hdu5164]ac自动机的更多相关文章
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- python爬虫学习(11) —— 也写个AC自动机
0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]
1212: [HNOI2004]L语言 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1367 Solved: 598[Submit][Status ...
- [AC自动机]【学习笔记】
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)To ...
- AC自动机 HDU 3065
大概就是裸的AC自动机了 #include<stdio.h> #include<algorithm> #include<string.h> #include< ...
- AC自动机 HDU 2896
n个字串 m个母串 字串在母串中出现几次 #include<stdio.h> #include<algorithm> #include<string.h> #inc ...
随机推荐
- API联调神器PostMan使用详解
简介 创建 + 测试:创建和发送任何的HTTP请求,请求可以保存到历史中再次执行 Organize:使用Postman Collections为更有效的测试及集成工作流管理和组织APIs docume ...
- srt字幕翻译
需要把字幕名改成i.txt 有有道和谷歌 代码: #Author:Chenglong Qian #Copyright :Chenglong Qian import json import reques ...
- mysql 使用记录
修改 mysql 数据库密码 mysqladmin -u username -h host_name password -P <port> "new_password" ...
- 转载-linux内核长什么样
来源:Linux中国 今天,我来为大家解读一幅来自 TurnOff.us 的漫画 "InSide The Linux Kernel" . TurnOff.us是一个极客漫画网站,作 ...
- BMP图片解析
本博客参考:https://www.cnblogs.com/l2rf/p/5643352.html 一.简介 BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Window ...
- Javascript-异步详解
- php 通过 yield 实现协程有什么使用场景
来源:https://segmentfault.com/q/1010000010018151 参考:https://www.cnblogs.com/lynxcat/p/7954456.html 协程可 ...
- 2019-2020-1 20199325《Linux内核原理与分析》第七周作业
第七周作业 1.进程描述符task_struct数据结构(一) 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. struct task_struct数据结构很 ...
- 15个有趣好玩的linux shell 命令
今天介绍一些有趣的linux shell命令,所有的命令都可以使用man + 命令名称 来查看完整的使用方法. 1,figlet 字符画 figlet 可以将英文字符串以字符画的形式输出: >& ...
- 浅析 JS 中的作用域链
作用域链的形成 在 JS 中每个函数都有自己的执行环境,而每个执行环境都有一个与之对应的变量对象.例如: var a = 2 function fn () { var a = 1 console.lo ...