zoukankan      html  css  js  c++  java
  • 洛谷 P3796 【模板】AC自动机(加强版)(AC自动机)

    题目链接:https://www.luogu.com.cn/problem/P3796

    AC自动机:复杂度$O( (N+M) imes L )$,N为模式串个数,L为平均长度,M为文章长度。

    insert:

      构造一个trie,然后标记一下每一个模式串的最后一个,即$vis$。

    get_fail:

      进行在trie上进行BFS,第一层点的失配指针指向根节点;之后的一个节点失配指针指向/他父亲的失配指针/指向的节点中/的儿子具有相同节点的位置。

      这里有一个小优化:fail是用来寻找失配时走到的位置的,走一个点fail的他的ch[i]一定是没有的。那么可以用这些ch指针直接指向它的fail的ch[i],可以发现这样操作之后,每个点的ch[i]直接指向了原本沿着失配边不停走的最终结果,这样的话,匹配时每次用ch指针的对象即可,不用一直沿fail边走看看这个点有没有ch[i]了。

    query:

      向下一层循环求解,直到fail不能走了,注意如果j不是终点,那么即ans[0]++,但最终不影响结果,因为统计时从1开始...

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 const int N=1000000+100;
     8 const int maxn=505;
     9 int fail[N],ch[N][26],vis[N];
    10 int ans[N];
    11 string s[maxn];
    12 int cnt;
    13 void insert(string s,int v){
    14     int u=0;
    15     int len=s.length();
    16     for(int i=0;i<len;i++){
    17         int id=s[i]-'a';
    18         if(!ch[u][id]) ch[u][id]=++cnt;
    19         u=ch[u][id];
    20     }
    21     vis[u]=v;
    22 }
    23 void get_fail(){
    24     int now=0;
    25     queue<int> q;
    26     for(int i=0;i<26;i++){
    27         if(ch[now][i]){
    28             q.push(ch[now][i]);
    29             fail[ch[now][i]]=now;
    30         }
    31     }
    32     while(!q.empty()){
    33         int u=q.front();
    34         q.pop();
    35         for(int i=0;i<26;i++){
    36             int v=ch[u][i];
    37             if(v) fail[v]=ch[fail[u]][i],q.push(v);
    38             else ch[u][i]=ch[fail[u]][i];//you hua
    39         }
    40     }
    41 }
    42 void query(string s){
    43     int now=0;
    44     int len=s.length();
    45     for(int i=0;i<len;i++){
    46         now=ch[now][s[i]-'a'];
    47         for(int j=now;j;j=fail[j]) ans[vis[j]]++;
    48     }
    49 }
    50 int main(){
    51     int n;
    52     while(scanf("%d",&n)){
    53         memset(vis,0,sizeof(vis));
    54         memset(ans,0,sizeof(ans));
    55         memset(ch,0,sizeof(ch));
    56         memset(fail,0,sizeof(fail));
    57         if(n==0) break;
    58         for(int i=1;i<=n;i++){
    59             cin>>s[i];
    60             insert(s[i],i);
    61         }
    62         get_fail();
    63         string str;
    64         cin>>str;
    65         query(str);
    66         int maxx=0;
    67         for(int i=1;i<=n;i++) maxx=max(maxx,ans[i]);
    68         printf("%d
    ",maxx);
    69         for(int i=1;i<=n;i++) if(ans[i]==maxx) cout<<s[i]<<endl;
    70     }
    71     return 0;
    72 }
    AC代码
  • 相关阅读:
    javascript清空数组的三种方法
    assigning to rvalue错误的原因与解决方法
    form表单提交的disabled属性踩坑记录(某个字段死活保存不上)
    java对两个字符串数组取交集、并集和差集
    vue2.x学习笔记(三十二)
    vue2.x学习笔记(三十)
    vue2.x学习笔记(二十九)
    vue2.x学习笔记(二十八)
    数据结构与算法之间的关系
    记一次解决CSS定位bug思路
  • 原文地址:https://www.cnblogs.com/New-ljx/p/12354855.html
Copyright © 2011-2022 走看看