【CodeChef-LYRC】Music & Lyrics【AC自动机】
2016-04-21 07:49
405 查看
【题目链接】
给出W个模板串和N个匹配串,问每个模板串在所有匹配串中一共出现了多少次。
先把所有模板串放进AC自动机,然后用每个匹配串在AC自动机上跑,走过的节点权值++。最后在fail树上做个前缀和,查询每个模板串的结尾节点的权值就好了。
一开始求前缀和写了深搜,但是看了策爷代码,发现可以利用求fail时的广搜队列来跑前缀和,orz%%%。
模板串和匹配串长度不一样,数组开小了WA了一发。
/* Pigonometry */
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 505, maxnode = 2500005, maxq = maxnode;
int n, val[maxn], fail[maxnode], son[maxnode][63], sum[maxnode], acmcnt, q[maxq], h, t;
char str[50005];
inline int get(char ch) {
if(ch >= 'a' && ch <= 'z') return ch - 'a';
if(ch >= 'A' && ch <= 'Z') return ch - 'A' + 26;
if(ch >= '0' && ch <= '9') return ch - '0' + 52;
if(ch == '-') return 62;
}
inline int insert() {
int now = 0, len = strlen(str);
for(int i = 0; i < len; i++) {
int &pos = son[now][get(str[i])];
if(!pos) pos = ++acmcnt;
now = pos;
}
return now;
}
inline void getfail() {
h = 0, t = 0;
for(int i = 0; i < 63; i++) if(son[0][i]) q[t++] = son[0][i];
while(h != t) {
int u = q[h++];
for(int i = 0; i < 63; i++)
if(!son[u][i]) son[u][i] = son[fail[u]][i];
else fail[q[t++] = son[u][i]] = son[fail[u]][i];
}
}
inline void work() {
int now = 0, len = strlen(str);
for(int i = 0; i < len; i++) {
now = son[now][get(str[i])];
sum[now]++;
}
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%s", str);
val[i] = insert();
}
getfail();
int T; scanf("%d", &T);
while(T--) {
scanf("%s", str);
work();
}
for(int i = t - 1; i >= 0; i--) sum[fail[q[i]]] += sum[q[i]];
for(int i = 1; i <= n; i++) printf("%d\n", sum[val[i]]);
return 0;
}
给出W个模板串和N个匹配串,问每个模板串在所有匹配串中一共出现了多少次。
先把所有模板串放进AC自动机,然后用每个匹配串在AC自动机上跑,走过的节点权值++。最后在fail树上做个前缀和,查询每个模板串的结尾节点的权值就好了。
一开始求前缀和写了深搜,但是看了策爷代码,发现可以利用求fail时的广搜队列来跑前缀和,orz%%%。
模板串和匹配串长度不一样,数组开小了WA了一发。
/* Pigonometry */
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 505, maxnode = 2500005, maxq = maxnode;
int n, val[maxn], fail[maxnode], son[maxnode][63], sum[maxnode], acmcnt, q[maxq], h, t;
char str[50005];
inline int get(char ch) {
if(ch >= 'a' && ch <= 'z') return ch - 'a';
if(ch >= 'A' && ch <= 'Z') return ch - 'A' + 26;
if(ch >= '0' && ch <= '9') return ch - '0' + 52;
if(ch == '-') return 62;
}
inline int insert() {
int now = 0, len = strlen(str);
for(int i = 0; i < len; i++) {
int &pos = son[now][get(str[i])];
if(!pos) pos = ++acmcnt;
now = pos;
}
return now;
}
inline void getfail() {
h = 0, t = 0;
for(int i = 0; i < 63; i++) if(son[0][i]) q[t++] = son[0][i];
while(h != t) {
int u = q[h++];
for(int i = 0; i < 63; i++)
if(!son[u][i]) son[u][i] = son[fail[u]][i];
else fail[q[t++] = son[u][i]] = son[fail[u]][i];
}
}
inline void work() {
int now = 0, len = strlen(str);
for(int i = 0; i < len; i++) {
now = son[now][get(str[i])];
sum[now]++;
}
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%s", str);
val[i] = insert();
}
getfail();
int T; scanf("%d", &T);
while(T--) {
scanf("%s", str);
work();
}
for(int i = t - 1; i >= 0; i--) sum[fail[q[i]]] += sum[q[i]];
for(int i = 1; i <= n; i++) printf("%d\n", sum[val[i]]);
return 0;
}
相关文章推荐
- 团队开发——个人工作总结03
- NYOJ-517-最小公倍数,大数啊~~~
- [HDU 5521] 2015ACM/ICPC亚洲区沈阳站 Meeting 最短路
- 使用Yeoman搭建 AngularJS 应用 (6) —— 让我们搭建一个网页应用
- 56. Merge Intervals
- 如何在 CentOS 7 中添加新磁盘而不用重启系统
- 如何在 CentOS 7 中添加新磁盘而不用重启系统
- 个人工作总结03
- 我是一个线程(修订版)
- Openstack学习笔记(十四)-Horizon学习笔记(四)
- [bzoj1799]同类分布 [bzoj4521]手机号码
- HARK学习(八)--LoadSourceLocation
- 梦见教训学生的周公解梦
- salesforce 零基础学习(十七)Trigger用法
- vi/vim常用命令
- 修改后的神经网络
- AFN 获取数据,数据解析:JSON 介绍
- Mini-Shell without pipes
- 团队项目个人工作总结(4月21日)
- 我是一个Java class