传送门:​​2222​


正要学AC自动机--发现  k*n=5*10^7  --  就用单纯的字典树过了--

建树--扫描字符串--统计---


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct trie{
trie * child[26];
int shu;
int hao;
}P[600000];
int ii=0,kp,op[10100];
trie * boot = & P[0];
void create(char xx[],int ii)//建树
{
trie * k=boot;
int j,ll=strlen(xx);
for (int i=0;i<ll;i++)
{
j=xx[i]-'a';
if (!k->child[j])
{
P[kp].hao=kp;
P[kp].shu=0;
k->child[j]=&P[kp++];
}
k=k->child[j];
}
op[ii]=k->hao;
}
void sou(char xx[])//匹配
{
trie * k=boot;
int j;
for (int i=0;xx[i];i++)
{
j=xx[i]-'a';
if (!k->child[j])
return;
k=k->child[j];
k->shu++;
}
}
void sol()
{
int n;scanf("%d",&n);
char ch[60];kp=1;
memset(P,0,sizeof(P));
for (int i=1;i<=n;i++)
{
scanf("%s",ch);
create(ch,i);
}
char opop[1000100];
scanf("%s",opop);
int ll=strlen(opop);
for (int i=0;i<ll;i++)
sou(opop+i);
int s=0;
for (int i=1;i<=n;i++)//统计
if (P[op[i]].shu)
s++;
printf("%d\n",s);
}
int main()
{
int t;scanf("%d",&t);
while (t--) sol();
return 0;
}


—————————————————————————————————————————————————————————————————————————————

AC机中主要的是fail指针的创建,这里采用bfs来一层一层的创建,每个结点的fail所指的层数当然小于它自身的层数呀,

然后第一层的都指向root,

剩下的举个例子

ABCDE 

AC机代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
long long ans ;
char ch[60];
char str[10001000];
struct node{
node * next[26];
node * fail;
int sum;
bool falg;
node():sum(0),falg(false),fail(NULL){
memset(next,0LL,sizeof(next));
}
};
node * root;
void build(){
int ll = strlen(ch),x;
node * p = root;
for (int i=0;i<ll;i++){
x = ch[i]-'a';
if (p->next[x]==NULL) p->next[x] = new node();
p = p->next[x];
}
p->sum++;
// printf("%s %d %d\n",ch,p->sum,p);
}

void dele(node * root){
for (int i=0;i<26;i++){
if (root->next[i]!=NULL){
dele(root->next[i]);
}
}
delete root;
}

void getfail(){
root->fail = root;
queue<node *> que;
que.push(root);
int ca = 2;
while (!que.empty()){
node * temp = que.front();
que.pop();
for (int i=0;i<26;i++){
if (temp->next[i]!=NULL){
node * p = temp;
que.push(p->next[i]);
while (p!=root){

if (p->fail->next[i]!=NULL){
temp->next[i]->fail = p->fail->next[i];
break;
}else{
p = p->fail;
}

}
if (p==root){
temp->next[i]->fail = root;
}
// temp->next[i]->sum += (temp->next[i]->fail->sum);
}
}
}
}
void sumToZero(node * p){
while (!p->falg){
ans += p->sum;

p->falg = true;

p = p->fail;
}
}
void AC(){
node * p = root;

int ll = strlen(str),x;

for (int i=0;i<ll;i++){

x = str[i] - 'a';
if (p->next[x]!=NULL){
p = p->next[x];
}else{
while (p!=root){
p = p->fail;
if (p->next[x]!=NULL){
p=p->next[x];
break;
}
}
}
// if (p->sum!=0){
// ans += p->sum;
sumToZero(p);
// printf("%c %d ---\n",str[i],ans);
// }
}
}

void slove(){
int n;scanf("%d",&n);
root = new node();
root->falg = true;
for (int i=0;i<n;i++){
scanf("%s",ch);
build();
}

getfail();

scanf("%s",str);
ans = 0;
AC();
printf("%lld\n",ans);
dele(root);
}
int main()
{
int T;scanf("%d",&T);
while (T--){
slove();
}
return 0;
}