目录
AC自动机
HDU 2896
指针写法(爆内存,MLE)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
#define mian main
#define ll long long
const int kind = 130;
string s;
struct node
{
node *fail; //失败指针
node *next[kind]; //Tire每个节点的个子节点(最多个字母)
int count; //是否为该单词的最后一个节点
int sum;
node() //构造函数初始化
{
fail=NULL;
count=0;
sum=0;
memset(next,NULL,sizeof(next));
}
}*q[501]; //队列,方便用于bfs构造失败指针
char str[10005]; //模式串
int head,tail; //队列的头尾指针
void insert(string str,node *root,int id){
node *p=root;
int i=0,index;
while(str[i])
{
index=str[i];
if(p->next[index]==NULL) p->next[index]=new node();
p=p->next[index];
i++;
}
p->count++; //在单词的最后一个节点count+1,代表一个单词
p->sum=id;
}
void build_ac_automation(node *root){
int i;
root->fail=NULL;
q[head++]=root;
while(head!=tail)
{
node *temp=q[tail++];
node *p=NULL;
for(i=0; i<130; i++)
{
if(temp->next[i]!=NULL)
{
if(temp==root) temp->next[i]->fail=root;
else
{
p=temp->fail;
while(p!=NULL)
{
if(p->next[i]!=NULL)
{
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL) temp->next[i]->fail=root;
}
q[head++]=temp->next[i];
}
}
}
}
int query(node *root,bool &flag,int id){
int i=0,cnt=0,index,len=strlen(str);
node *p=root;
while(str[i])
{
index=str[i];
while(p->next[index]==NULL && p!=root) p=p->fail;
p=p->next[index];
p=(p==NULL)?root:p;
node *temp=p;
while(temp!=root && temp->count!=-1)
{
cnt+=temp->count;
if(temp->count>0){
if(flag==true) cout<<"web "<<id<<": ";
cout<<p->sum<<" ";
flag=false;
}
temp->count=-1;
temp=temp->fail;
}
i++;
}
return cnt;
}
int main()
{
int n;
int ca=0;
while(cin>>n){
ca++;
node root;
for(int i=1;i<=n;i++){
cin>>s;
insert(s,&root,i);
}
build_ac_automation(&root);
int m;
cin>>m;
int ans=0;
bool flag=true;
for(int i=1;i<=m;i++){
cin>>str;
flag=true;
if(query(&root,flag,i)!=0) ans++;
if(flag==false) cout<<endl;
}
cout<<"total: "<<ans<<endl;
}
return 0;
}
数组写法(AC)
#include<bits/stdc++.h>
#define N 210*500
using namespace std;
queue<int>q;
struct Aho_Corasick_Automaton{
int c[N][128],val[N],fail[N],cnt;
void ins(char *s,int id){
int len=strlen(s);int now=0;
for(int i=0;i<len;i++){
int v=s[i];
if(!c[now][v])c[now][v]=++cnt;
now=c[now][v];
}
val[now]=id;
}
void build(){
for(int i=0;i<128;i++)if(c[0][i])fail[c[0][i]]=0,q.push(c[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<128;i++)
if(c[u][i])fail[c[u][i]]=c[fail[u]][i],q.push(c[u][i]);
else c[u][i]=c[fail[u]][i];
}
}
bool used[510];
int query(char *s,int id,int n){
bool flag=false;
memset(used,false,sizeof(used));
int len=strlen(s);int now=0,ans=0;
for(int i=0;i<len;i++){
now=c[now][s[i]];
for(int t=now;t&&~val[t];t=fail[t]){
if(val[t]!=0){
// cout<<val[t]<<endl;
used[val[t]]=true;//val[t]=-1;
flag=true;
}
}
}
if(flag==false) return false;
printf("web %d:",id);
for(int i=1;i<=n;i++){
if(used[i]) cout<<" "<<i;
}
cout<<endl;
return true;
}
}AC;
int n;char p[1000005];
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)scanf("%s",p),AC.ins(p,i);
AC.build();
int m;
cin>>m;
int ans=0;
for(int i=1;i<=m;i++){
scanf("%s",p);
if(AC.query(p,i,n)) ans++;
// int ans=AC.query(p);
}
printf("total: %d\n",ans);
}
return 0;
}