首页 > 其他 > 详细

AC自动机妙用

时间:2014-04-10 21:54:46      阅读:404      评论:0      收藏:0      [点我收藏+]

理解题意之后,很自然的想到了用AC自动机搞,结果网上一搜,全是暴搜,按照自己的思想,AC自动机搞起,果然在提交了数次之后,看到了Accept。

AC自动机需要三个步骤:

第一步:建立字典树;

第二步:为字典树建立 Fail 指针 ;

第三步:进行匹配;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include<iostream>
#include<string>
#include<string.h>
#include<cctype>
#include<queue>
#include<stdio.h>
 
#define max(x,y) ((x) > (y) ? (x) : (y))
 
using namespace std ;
 
struct Node {
    Node *next[26] ;
    Node *fail ;
    bool is_over ;
    int len ;
};
 
Node* new_node()    {
    Node *root = new Node ;
    root ->fail = NULL ;
    for(int i = 0 ; i< 26 ; i++)
        root->next[i] = NULL ;
    root ->is_over = false ;
    return root ;
}
 
void build_tree( Node *root , char *s ) {
    int len = strlen(s) ;
    for(int i = 0 ; i < len ; i++)   {
        if(root->next[s[i] - ‘a‘] == NULL)
            root->next[s[i] - ‘a‘] = new_node() ;
        root = root ->next[s[i] - ‘a‘] ;
    }
    root ->is_over = true ;
    root ->len = len ;
}
 
void build_fail(Node *root) {
    Node *r = root ;
    queue< Node* > q ;
    q.push(root) ;
    while(!q.empty())   {
        r = q.front() ;
        q.pop() ;
        Node *p = r ;
        for(int i = 0 ; i < 26 ; i++)    {
            if(p->next[i] != NULL)   {
                if(p == root)   {
                    p->next[i]->fail = root ;
                    q.push(p->next[i]) ;
                    continue ;
                }
                while(r->fail->next[i] == NULL && r ->fail != root)
                    r = r->fail ;
                if(r->fail ->next[i] != NULL)
                    p ->next[i]->fail = r ->fail ->next[i] ;
                else
                    p ->next[i] ->fail = root ;
                q.push(p->next[i]) ;
            }
        }
    }
}
 
int A_C(Node *root , char *s)   {
    int len = strlen(s) ;
    Node *r = root ;
    int count = 0 ;
    for(int i = 0 ; i < len ; i++)   {
        if(!isalpha(s[i]))
            continue ;
        if(r->next[s[i]-‘a‘] != NULL)    {
            r = r ->next[s[i]-‘a‘] ;
            if(r->is_over && !(islower(s[i+1])) && !(islower(s[i - r->len])) )   
                count++ ;
        }
        else {
            while(r->next[s[i]-‘a‘] == NULL && r != root )
                r = r ->fail ;
            if(r ->next[s[i] - ‘a‘] != NULL)
                r = r ->next[s[i] - ‘a‘] ;
            else
                r = root ;
            if(r->is_over && (!(isalpha(s[i+1])) ) && !(islower(s[i - r->len]))   )  
                count++ ;  
        }
    }
     
    return count ;
}
 
 
int main()  {
    int n , m ;
    int t = 1 ;
    while(scanf("%d%d",&n,&m) == 2) {
        Node *root = new_node() ;
        Node *r = root ;
        while(n--)  {
            char s[30] ;
            scanf("%s",&s) ;
            getchar() ;
            build_tree(root,s) ;
            root = r ;
        }
        r->fail = NULL ;
        root = r ;
        build_fail(r) ;
        char str[30][100] ;
        char str1[30][100] ;
        int count[30] = {0} ;
        int ma = 0 ;
        for(int i = 0 ; i < m ; i++) {
            gets(str[i]) ;
            strcpy(str1[i],str[i]) ;
            int len = strlen(str[i]) ;
            for(int j = 0 ; j < len ; j++)
                if(isupper(str[i][j]))
                    str[i][j] += 32 ;
            count[i] = A_C(root,str[i]) ;
            ma = max(ma,count[i]) ;
        }
        cout << "Excuse Set #" << t++ << endl;
        for(int k = 0 ; k < m ; k++)
            if(count[k] == ma) 
                cout << str1[k] << endl ;
            cout << endl ;
    }
    return 0 ;
}

 

AC自动机妙用,布布扣,bubuko.com

AC自动机妙用

原文:http://www.cnblogs.com/scottding/p/3656338.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!