Description
给定T组数据n个单词一个字符串s求s中有多少给出的单词出现
Solution
无力吐槽题号
ac自动机裸题模板,学习了 所谓ac自动机就是一棵带fail指针的trie,t(i)的fail表示作为t(i)后缀的另一字符串的前缀位置,然后这个fail是可以bfs出来的
还有就是最好记路strlen不然每次会TLE。神奇
辣鸡csdn卡死害我重写了三遍
为了应对MLE这里补上指针版本的
Code
#include <stdio.h>
#include <string.h>
#include <queue>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define N 500005
#define L 27
using namespace std;
int rc[N][L], p[N], f[N], cnt, len;
char s[
1000001];
inline void getFail(){
queue<int> q;
rep(i,
'a',
'z'){
if (rc[
0][i -
'a']){
q.push(rc[
0][i -
'a']);
}
}
while (!q.empty()){
int now = q.front(); q.pop();
rep(i,
'a',
'z'){
if (rc[now][i -
'a']){
q.push(rc[now][i -
'a']);
int v = f[now];
while (v && !rc[v][i -
'a']){
v = f[v];
}
f[rc[now][i -
'a']] = rc[v][i -
'a'];
}
}
}
}
inline void insert(){
int now =
0;
rep(i,
0, len -
1){
int tar = s[i] -
'a';
if (!rc[now][tar]){
rc[now][tar] = ++ cnt;
}
now = rc[now][tar];
}
p[now] +=
1;
}
inline void query(){
int now =
0;
int ans =
0;
rep(i,
0, len -
1){
int tar = s[i] -
'a';
while (now && !rc[now][tar]){
now = f[now];
}
now = rc[now][tar];
for (
int tmp = now; tmp; tmp = f[tmp]){
ans += p[tmp];
p[tmp] =
0;
}
}
printf(
"%d\n", ans);
}
int main(
void){
int T;
scanf(
"%d", &T);
while (T --){
cnt =
0;
fill(rc,
0);
fill(f,
0);
fill(p,
0);
int n;
scanf(
"%d", &n);
rep(i,
1, n){
scanf(
"%s", s);
len =
strlen(s);
insert();
}
getFail();
scanf(
"%s", s);
len =
strlen(s);
query();
}
return 0;
}
#include <stdio.h>
#include <
string.h>
#include <queue>
#define rep(i, st, ed)
for (
int i = st; i <= ed; i +=
1)
#define fill(x, t) memset(x, t, sizeof(x))
#define N
1001001
struct node{
node *
next[
26];
node *fail;
int count;
node(){
fail =
NULL;
rep(i,
0,
25){
next[i] =
NULL;
}
count =
0;
}
}*root;
inline void ins(char *str){
node *
now = root;
int len = strlen(str);
rep(i,
0,
len -
1){
int tar = str[i] -
if (
now->
next[tar] ==
NULL){
now->
next[tar] =
new node();
}
now =
now->
next[tar];
}
now->count +=
1;
}
using std:: queue;
queue<struct node *> que;
inline void getFail(){
int head =
0, tail =
0;
que.push(root);
while (!que.
empty()){
node *
now = que.front(); que.pop();
rep(i,
0,
25){
if (
now->
next[i] !=
NULL){
if (
now == root){
now->
next[i]->fail = root;
}
else{
node *tmp =
now->fail;
while (tmp !=
NULL){
if (tmp->
next[i] !=
NULL){
now->
next[i]->fail = tmp->
next[i];
break;
}
tmp = tmp->fail;
}
if (tmp ==
NULL){
now->
next[i]->fail = root;
}
}
que.push(
now->
next[i]);
}
}
}
}
inline
int query(char *str){
int len = strlen(str);
int ret =
0;
node *
now = root;
rep(i,
0,
len -
1){
int tar = str[i] -
while (
now->
next[tar] ==
NULL &&
now != root){
now =
now->fail;
}
now =
now->
next[tar];
if (
now ==
NULL){
now = root;
}
node *tmp =
now;
while (tmp != root && tmp->count != -
1){
ret += tmp->count;
tmp->count = -
1;
tmp = tmp->fail;
}
}
return ret;
}
char str[N];
int main(void){
int T;
scanf(
"%d", &T);
while (T --){
int n;
scanf(
"%d", &n);
root =
new node();
rep(i,
1, n){
scanf(
"%s", str);
ins(str);
}
scanf(
"%s", str);
getFail();
int ans = query(str);
printf(
"%d\n", ans);
}
return
0;
}
转载请注明原文地址: https://ju.6miu.com/read-550026.html