[洛谷3808]【模板】AC自动机(简单版)

题目大意:
  给定$n$个模式串$p(\sum|p_i|\le10^6)$和一个$t(|t|\le10^6)$,求在$t$中被匹配的$p$的个数。

思路:
  AC自动机模板题,注意$t$中一个字符可能对应自动机上多个结点,因此需要按照失配指针跳转统计。统计过的结点需要特殊标记,避免重复统计,否则会超时。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 }
11 const int N=1e6+1,S=26;
12 char s[N];
13 int ans=0;
14 class AhoCorasick {
15     private:
16         std::queue<int> q;
17         int val[N],ch[N][S],fail[N];
18         int sz,new_node() {
19             return ++sz;
20         }
21         int idx(const char &c) const {
22             return c-'a';
23         }
24     public:
25         void insert(const char s[]) {
26             int p=0;
27             for(register int i=0;s[i];i++) {
28                 if(!ch[p][idx(s[i])]) ch[p][idx(s[i])]=new_node();
29                 p=ch[p][idx(s[i])];
30             }
31             val[p]++;
32         }
33         void get_fail() {
34             for(register int i=0;i<S;i++) {
35                 if(ch[0][i]) q.push(ch[0][i]);
36             }
37             while(!q.empty()) {
38                 const int &x=q.front();
39                 for(register int i=0;i<S;i++) {
40                     if(!ch[x][i]) {
41                         ch[x][i]=ch[fail[x]][i];
42                         continue;
43                     }
44                     fail[ch[x][i]]=ch[fail[x]][i];
45                     q.push(ch[x][i]);
46                 }
47                 q.pop();
48             }
49         }
50         void find(const char s[]) {
51             int p=0;
52             for(register int i=0;s[i];i++) {
53                 p=ch[p][idx(s[i])];
54                 for(register int q=p;q&&~val[q];q=fail[q]) {
55                     ans+=val[q];
56                     val[q]=-1;
57                 }
58             }
59         }
60 };
61 AhoCorasick ac;
62 int main() {
63     const int n=getint();
64     for(register int i=0;i<n;i++) {
65         scanf("%s",s);
66         ac.insert(s);
67     }
68     ac.get_fail();
69     scanf("%s",s);
70     ac.find(s);
71     printf("%d\n",ans);
72     return 0;
73 }

 

posted @ 2018-03-14 19:10  skylee03  阅读(135)  评论(0编辑  收藏  举报