传送门:点击打开链接
题意:给一个字典,再给一个查询串,问字典中的单词一共在这个查询串中出现了多少次。
思路:裸AC自动机。。第一次做,照着bin神代码写了个模板留着以后贴
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck printf("fuck")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
/*MX为总长度*/
const int MX = 500000 + 5;
struct AC_machine {
int rear, root;
int Next[MX][26], Fail[MX], End[MX];
void Init() {
rear = 0;
root = New();
}
int New() {
rear++;
End[rear] = 0;
for(int i = 0; i < 26; i++) {
Next[rear][i] = -1;
}
return rear;
}
void Add(char*A) {
int n = strlen(A), now = root;
for(int i = 0; i < n; i++) {
int id = A[i] - 'a';
if(Next[now][id] == -1) {
Next[now][id] = New();
}
now = Next[now][id];
}
End[now]++;
}
void Build() {
queue<int>Q;
Fail[root] = root;
for(int i = 0; i < 26; i++) {
if(Next[root][i] == -1) {
Next[root][i] = root;
} else {
Fail[Next[root][i]] = root;
Q.push(Next[root][i]);
}
}
while(!Q.empty()) {
int u = Q.front();
Q.pop();
for(int i = 0; i < 26; i++) {
if(Next[u][i] == -1) {
Next[u][i] = Next[Fail[u]][i];
} else {
Fail[Next[u][i]] = Next[Fail[u]][i];
Q.push(Next[u][i]);
}
}
}
}
int Query(char *S) {
int n = strlen(S), now = rear, ret = 0;
for(int i = 0; i < n; i++) {
now = Next[now][S[i] - 'a'];
int temp = now;
while(temp != root) {
ret += End[temp];
End[temp] = 0;
temp = Fail[temp];
}
}
return ret;
}
} AC;
char A[100], B[MX * 2];
int main() {
int T, n; //FIN;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
AC.Init();
for(int i = 1; i <= n; i++) {
scanf("%s", A);
AC.Add(A);
}
AC.Build();
scanf("%s", B);
printf("%d\n", AC.Query(B));
}
return 0;
}