您的位置:首页 > 其它

HDU 2896 AC自动机

2013-07-23 02:30 337 查看
中文题,题意就不解释了。

这道题把我坑了下,应该是做题不仔细的原因,一开始我以为是26个字母的(没认真读题,看样例的结果) ,然后RE了好几发,最多发现题目里的描述是ASCLL码表里面的可见字符,然后将建字典树过程中的0 - 25的循环改成0 - 127 就过了。

讲一下思路,这道题就是AC自动机的模版题,唯一需要注意的就是加一个id的域来存这个字符串的序号,最后输出的时候要按从小到大的顺序,我直接全部扔进set输出了。

不过我感觉数据有点水啊。。。总感觉A的不是很踏实。

加了释放内存,但是发现内存没比原来的少,难道数据只有一组o(︶︿︶)o 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) ( x << 1 )
#define RR(x) ( x << 1 | 1 )
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
using namespace std;

struct node {
node *fail ;
node *next[128] ;
int count ;
int id ;
node() {
fail = 0 ;
count = 0 ;
mem(next , 0) ;
id = 0 ;
}
}*qe[1000005] ;
node *root = 0 ;
//insert a[] .
void insert(char *a,int id) {
node *p = root ;
int l = strlen(a) ;
for (int i = 0 ; i < l ; i ++ ) {
int tt = a[i] ;
if(p -> next[tt] == 0) {
p -> next[tt] = new node() ;
}
p = p -> next[tt] ;
}
p -> count ++ ;
p -> id = id ;
}
//build *fail .
void build() {
root -> fail = 0 ;
int h = 0 , t = 0 ;
qe[h ++ ] = root ;
while(h > t) {
node *temp = qe[t ++ ] ;
node *p = 0 ;
for (int i = 0 ; i < 128 ; i ++ ) {
if(temp -> next[i] != 0) {
if(temp == root)temp -> next[i] -> fail = root ;
else {
p = temp -> fail ;
while(p != 0) {
if(p -> next[i] != 0) {
temp -> next[i] -> fail = p -> next[i] ;//找到匹配
break ;
}
p = p -> fail ;
}
if(p == 0)temp -> next[i] -> fail = root ;//如果没找到,则将fail指向root
}
qe[h ++ ] = temp -> next[i] ;
}
}
}
}
set<int>anss[1111] ;
int search(char *a ,int id) {
int l = strlen(a) ;
node *p = root ;
int ans = 0 ;
for (int i = 0  ; i < l ; i ++ ) {
int tt = a[i] ;
while(p -> next[tt] == 0 && p != root)p = p -> fail ;
p = p -> next[tt] ;
p = (p == 0) ? root : p ;
node *temp = p ;
while(temp != root && temp -> count != 0) {
ans += temp -> count ;
anss[id].insert(temp -> id) ;
//temp -> count = -1 ;
temp = temp -> fail ;
}
}
return ans ;
}

void deleteAll(node *p){
for (int i = 0 ; i < 128 ; i ++ )
if(p -> next[i] != 0){
deleteAll(p -> next[i]) ;
}
delete p ;
}
char a[11111] ;
int num[1111] ;
int main() {
int n ;
cin >> n ;
getchar() ;
root = new node() ;
for (int i = 1 ; i <= n ;i ++ ){
gets(a) ;
insert(a ,i ) ;
}
int m ;
cin >> m ;
getchar() ;
build() ;
for (int i = 1 ; i <= m ;i ++ ){
gets(a) ;
num[i] = search(a , i) ;
}
int cc = 0 ;
for (int i = 1 ; i <= m ;i ++ ){
if(num[i]){
printf("web %d:",i) ;
for(set<int>::iterator p = anss[i].begin() ; p != anss[i].end() ; ++ p)
cout <<" "<< *p ;
cc ++ ;
puts("") ;
}
}
printf("total: %d\n",cc) ;
deleteAll(root) ;
return 0 ;
}

贴一个AC自动机静态的模版

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include <set>
using namespace std;
char ss[1000010];
int n,cnt,ans;
struct node {
int num;
int next[128];
int fail;
int id ;
void init() {
memset(next,-1,sizeof(next));
fail=-1;
num=0;
id = 0 ;
}
} a[500000];
void insert(char s[],int id) {
int p=0,i=0;
int len=strlen(s);
while(i<len) {
int k=s[i] ;
if(a[p].next[k]==-1) {
a[cnt].init();
a[p].next[k]=cnt++;
}
i++;
p=a[p].next[k];
}
a[p].num++;
a[p].id = id ;
}
queue<int>q;
void ac_bfs() {
q.push(0);
while(!q.empty()) {
int p=q.front();
q.pop();
int fail=0;
for(int i=0; i<128; i++)if(a[p].next[i]!=-1) {
if(p==0) {
a[a[p].next[i]].fail=p;
} else {
fail=a[p].fail;
while(fail!=-1) {
if(a[fail].next[i]!=-1) {
a[a[p].next[i]].fail=a[fail].next[i];
break;
}
fail=a[fail].fail;
}
if(fail==-1)a[a[p].next[i]].fail=0;
}
q.push(a[p].next[i]);
}
}
}
set<int>fk[1111] ;
int query(char s[] ,int id) {
int i=0,len=strlen(s);
int p=0,ans=0;
while(i<len) {
int k=s[i] ;
while(a[p].next[k]==-1&&p!=0)p=a[p].fail;
p=a[p].next[k];
p=(p==-1)?0:p;
int tmp=p;
while(tmp!=0 && a[tmp].num != 0) {
ans+=a[tmp].num;
fk[id].insert(a[tmp].id) ;
tmp=a[tmp].fail;
}
i++;
}
return ans;
}

char virus[11111] ;
int fkk[1111] ;
int main() {
int n ;
cin >> n ;
cnt = 1 ;
a[0].init() ;
getchar() ;
for (int i = 1 ; i <= n ; i ++ ) {
gets(virus) ;
insert(virus,i) ;
}
int m ;
cin >> m ;
ac_bfs() ;
getchar() ;
int cc = 0 ;
for (int i = 1 ; i <= m ; i ++ ) {
gets(virus) ;
fkk[i] = query(virus , i) ;
}
for (int i = 1 ; i <= m ; i ++ ) {
if(fkk[i]) {
printf("web %d:",i) ;
for(set<int>::iterator p = fk[i].begin() ; p != fk[i].end() ; ++ p)
cout <<" "<< *p ;
cc ++ ;
puts("") ;
}
}
printf("total: %d\n",cc) ;
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: