[2015hdu多校联赛补题]hdu5384 Danganronpa

时间:2023-03-09 15:14:56
[2015hdu多校联赛补题]hdu5384 Danganronpa

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5384

题意:函数f(A, B)定义:A、B为字符串,f(A, B)为A中有多少个不同的B(ex:f("ababa", "aba")==2   f("ababa", "bab")==1),现在给你一组A串,一组B串,问你对每个A串的[2015hdu多校联赛补题]hdu5384 Danganronpa是多少

解:ac自动机模板题,可以把A串用'z'+1,连成一个串处理起来比较方便

 /*
* Problem: hdu5384 Danganronpa
* Author: SHJWUDP
* Created Time: 2015/8/13 星期四 14:38:23
* File Name: 1006.cpp
* State: Accepted
* Memo: ac自动机
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue> using namespace std; const int MaxA=1e5+;
const int MaxB=7e5+; const int SIGMA_SIZE=; struct AhoCorasickAutomata {
int ch[MaxB][SIGMA_SIZE];
int val[MaxB];
int sz;
int f[MaxB], last[MaxB]; int newNode() {
memset(ch[sz], , sizeof(ch[sz]));
val[sz]=;
return sz++;
} void init() {
sz=;
newNode();
} int id(char c) {
return c-'a';
} void insert(char* p) {
int u=;
while(*p) {
int c=id(*p++);
if(!ch[u][c]) ch[u][c]=newNode();
u=ch[u][c];
}
val[u]++;
} void getFail() {
queue<int> Q;
f[]=;
for(int c=; c<SIGMA_SIZE; c++) {
int u=ch[][c];
if(u) { f[u]=; Q.push(u); last[u]=; }
} while(!Q.empty()) {
int r=Q.front(); Q.pop();
for(int c=; c<SIGMA_SIZE; c++) {
int u=ch[r][c];
if(!u) { ch[r][c]=ch[f[r]][c]; continue; }
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]];
}
}
} long long dealAns(int u) {
long long res=;
while(u) {
res+=val[u];
// val[u]=0;
u=last[u];
}
return res;
} void find(char * T, long long * ans) {
int u=;
int pos=;
long long sum=, ltsum=;
for(int i=; T[i]; i++) {
int c=id(T[i]);
u=ch[u][c];
if(val[u]) sum+=dealAns(u);
else if(last[u]) sum+=dealAns(last[u]);
if(T[i]=='z'+) {
ans[pos++]+=sum-ltsum;
ltsum=sum;
}
}
}
} ac; int n, m;
char str[MaxB];
long long ans[MaxA];
char gogogo[MaxA];
int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
//freopen("out", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
int len=;
for(int i=; i<n; i++) {
scanf("%s", str+len);
while(str[len]) len++;
str[len++]='z'+;
}
str[len]='\0';
ac.init();
for(int i=; i<m; i++) {
scanf("%s", gogogo);
ac.insert(gogogo);
}
ac.getFail();
memset(ans, , sizeof(ans));
ac.find(str, ans);
for(int i=; i<=n; i++) {
printf("%I64d\n", ans[i]);
}
}
return ;
}