【CodeChef-LYRC】Music & Lyrics【AC自动机】

来源:互联网 发布:博泰与创业软件 编辑:程序博客网 时间:2024/06/05 13:44

【题目链接】

给出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;}


0 0