您的位置:首页 > 其它

[c]sdnuoj1116 AC自动机

2015-08-07 22:39 204 查看
http://210.44.14.31/problem/show/1116

题目标题:Keywords Sreach

题目大意:给出n个字符串和一个匹配串,问有多少字符串在匹配串当中出现的

这个题是AC自动机的一道基础题,做这道题我用了好几天的功夫去查AC自动机的原理与解决方法,有了前几天的基础今天我只用了两个小时就A出了这道题(第一次交就A了吓到我了)AC自动机是基于字母树与KMP算法的一种算法,通过在字母树中建立fail结点来增加查找的效率,做法在这里我就不详细说了,网上的各位大神比我说的要清楚的多

#include<iostream>
#include<stdio.h>
#include<string>
#include<stdlib.h>
#include<queue>
using namespace std;

struct Node{
Node *next[26];
Node *fail;
int value;
int num;
};

Node head;
queue<Node*> Qu;

Node* Create(){
Node *p;
p=(Node*)malloc(sizeof(Node));
for(int i=0;i<26;i++){
p->next[i]=NULL;
}
p->num=0;
return p;
}

void Make(string x){
Node *p=&head;
for(int i=0;i<x.size();i++){
int n=int(x[i]-'a');
if(p->next
==NULL){
Node *q=Create();
q->value=int(x[i]-'a');
q->fail=p;
p->next
=q;
}
p=p->next
;
}
p->num++;
}

void MakeFail(){
Node *p=&head;
Qu.push(p);
while(Qu.size()!=0){
Node *q=Qu.front();
for(int i=0;i<26;i++){
if(q->next[i]!=NULL)
Qu.push(q->next[i]);
}
if(q->fail!=&head && q!=&head){
Node *r=q->fail->fail;
while(r->next[q->value]==NULL && r!=&head){
r=r->fail;
}
if(r->next[q->value]!=NULL) q->fail=r->next[q->value];
else q->fail=&head;
}
Qu.pop();
}
}

int Solve(string x){
head.fail=&head;
int j=0;
int re=0;
Node *p=&head;
Node *t;
for(int i=0;i<x.size();i++){
while(p->next[x[i]-'a']==NULL && p!=&head) p=p->fail;
p=(p->next[x[i]-'a']==NULL)?&head:p->next[x[i]-'a'];
t=p;
while(t!=&head){
re+=t->num;
t->num=0;
t=t->fail;
}
}
return re;
}

int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
string x;
cin>>x;
Make(x);
}
MakeFail();
string pp;
cin>>pp;
cout<<Solve(pp);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: