第一次写AC自动机
简单版的这道题可以在进行匹配的时候剪一下枝,应为之前比配过了,不用在匹配了。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
using namespace std;
const int MAXN=1e6+10;
queue<int> que;
struct AC{
int tr[MAXN][26],fail[MAXN],val[MAXN],tot;
void insert(char *s){
int n=strlen(s+1),p=0;
for(int i=1;i<=n;i++){
if(!tr[p][s[i]-'a'])
tr[p][s[i]-'a']=++tot;
p=tr[p][s[i]-'a'];
}
val[p]++;
}
void getfail(){
while(!que.empty()) que.pop();
for(int i=0;i<26;i++)
if(tr[0][i])
que.push(tr[0][i]);
while(!que.empty()){
int u=que.front();que.pop();
for(int i=0;i<26;i++)
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],que.push(tr[u][i]);
else tr[u][i]=tr[fail[u]][i];
}
// for(int i=0;i<=tot;i++) cout<<fail[i]<<" ";cout<<endl;
// for(int i=0;i<=tot;i++) cout<<val[i]<<" ";cout<<endl;
}
int ask(char *s){
int n=strlen(s+1),p=0,ans=0;
for(int i=1;i<=n;i++){
p=tr[p][s[i]-'a'];
for(int t=p;t&&val[t]!=-1;t=fail[t])
ans+=val[t],val[t]=-1;
}
return ans;
}
}ac;
int n;
char s[MAXN];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s+1);
ac.insert(s);
}
ac.getfail();
scanf("%s",s+1);
int ans=ac.ask(s);
printf("%d\n",ans);
return 0;
}
加强版的题,就不能剪枝了,因为要求出每个模式串出现的次数。
可以在 #trie# 的末节点上记录该串的 #id# 然后每次匹配到就给它++就行了。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int MAXN=1e6+10;
queue<int> que;
int cnt[160],ans,n;
char s[160][100],str[MAXN];
struct AC{
int tr[16000][26],fail[MAXN],val[MAXN],tot;
void init(){
memset(cnt,0,sizeof(cnt));
memset(tr,0,sizeof(tr));
memset(fail,0,sizeof(fail));
memset(val,0,sizeof(val));
tot=0;
ans=0;
}
void insert(char *s,int id){
int n=strlen(s+1),p=0;
for(int i=1;i<=n;i++){
if(!tr[p][s[i]-'a']) tr[p][s[i]-'a']=++tot;
p=tr[p][s[i]-'a'];
}
val[p]=id;
}
void getfail(){
while(!que.empty()) que.pop();
for(int i=0;i<26;i++)
if(tr[0][i]) que.push(tr[0][i]);
while(!que.empty()){
int u=que.front();que.pop();
for(int i=0;i<26;i++)
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],que.push(tr[u][i]);
else tr[u][i]=tr[fail[u]][i];
}
}
void ask(char *s){
int n=strlen(s+1),p=0;
for(int i=1;i<=n;i++){
p=tr[p][s[i]-'a'];
for(int t=p;t;t=fail[t])
if(val[t]) cnt[val[t]]++,ans=max(ans,cnt[val[t]]);
}
}
}ac;
int main(){
while(~scanf("%d",&n)){
if(!n) break;
ac.init();
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1),
ac.insert(s[i],i);
ac.getfail();
scanf("%s",str+1);
ac.ask(str);
printf("%d\n",ans);
for(int i=1;i<=n;i++) if(cnt[i]==ans) printf("%s\n",s[i]+1);
}
return 0;
}
原文地址:https://www.cnblogs.com/BakaCirno/p/11771700.html
时间: 2024-11-13 06:34:46