[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 ...
随机推荐
- 【题解】P1291 百事世界杯之旅 - 期望dp
P1291 [SHOI2002]百事世界杯之旅 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 "--在 \ ...
- bash cookbook
目录 简介 变量 静态变量 变量操作 数组 应用 四则运算 条件测试 整数测试 文件测试 字符测试 组合条件测试 选择语句 循环语句 for--有限循环 while--无线循环 until conti ...
- pytorch 中word embedding 词向量的使用
- JDBC 进阶:使用封装通用DML DQL 和结构分层以及at com.mysql.jdbc.PreparedStatement.setTimestamp空指针异常解决
准备: 数据表 CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(10) DEFAULT ...
- Bat 脚本 删除某一行
findstr /v /i /c:"kiwi" /c:"oranges" myfile.txt >newfile.txt
- Windows 切换 working directory
用函数 _chdir() 例如用计划任务启动,pwd 是 system32 使用相对路径的地方会出错. 在 main 函数刚启动的时候转换一下 working directory 可解.
- QT bug ig9icd64.dll
QT bug ig9icd64.dll bugintel ig9icd64.dll 处有未经处理的异常 遇到了一个 奇奇怪怪的bug, 一般的QT程序中 在main.cpp 中初始化一个窗口进行显示后 ...
- Scala的Higher-Kinded类型
Scala的Higher-Kinded类型 Higher-Kinded从字面意思上看是更高级的分类,也就是更高一级的抽象.我们先看个例子. 如果我们要在scala中实现一个对Seq[Int]的sum方 ...
- HashMap源码解析JDK8
一.HashMap基础 1.1 HashMap的定义 我们先看一下HashMap的定义: public class HashMap<K,V> extends AbstractMap< ...
- numpy库的学习笔记
一.ndarray 1.numpy 库处理的最基础数据类型是由同种元素构成的多维数组(ndarray),简称“数组”. 2.ndarray是一个多维数组的对象,ndarray数组一般要求所有元素类型相 ...