• [洛谷P3796][题解][模板]AC自动机


    至于AC自动机基础的话推荐yyb's blog

    如果看了还是不会的话就像我一样啃一整天画个图想一想就好啦

    AC自动机其实就是一种多模匹配算法,他约等于KMP思想+Trie结构(反正说了也没用)

    这道题主要是注意统计答案,可以在标记end时记上顺序并在统计答案时用结构体记录

    然后数据有很多组注意清零(我因为ans没清零WA了n次)

    Code:(与yyb的代码有相似之处毕竟是看着学的嘛

     1 #include<bits/stdc++.h>
     2 #define debug cout<<"AJH AK IOI!!!"<<endl
     3 using namespace std;
     4 int cnt,n;
     5 string ss[160];
     6 struct Node {
     7     int fail,ed,son[26];
     8 }tr[100510];
     9 struct Ans {//统计答案,ct为出现次数,idx为编号(输出用) 
    10     int ct,idx;
    11 }ans[100510];
    12 inline bool cmp(Ans a,Ans b){
    13     if(a.ct==b.ct)return a.idx<b.idx;
    14     return a.ct>b.ct;
    15 }
    16 inline void Clear(int now){
    17     tr[now].ed=0;
    18     tr[now].fail=0;
    19     memset(tr[now].son,0,sizeof(tr[now].son));
    20 }
    21 inline void Insert(string s,int nownum){
    22     int len=s.length(),now=0,tmp;
    23     for(int i=0;i<len;i++){
    24         tmp=s[i]-'a';
    25         if(!tr[now].son[tmp]){
    26             tr[now].son[tmp]=++cnt;//AC自动机基础操作,注意清零 
    27             Clear(cnt);
    28         }
    29         now=tr[now].son[tmp];
    30     }
    31     tr[now].ed=nownum;//插入单词时记录顺序 
    32 }
    33 inline void Fail(){
    34     queue<int>q;
    35     for(int i=0;i<26;i++){
    36         if(tr[0].son[i]){
    37             tr[tr[0].son[i]].fail=0;
    38             q.push(tr[0].son[i]);
    39         }
    40     }
    41     while(!q.empty()){
    42         int now=q.front();
    43         q.pop();
    44         for(int i=0;i<26;i++){
    45             if(tr[now].son[i]){
    46                 tr[tr[now].son[i]].fail=tr[tr[now].fail].son[i];
    47                 //非常巧妙的操作,避免了一步一步向上跳
    48                 //可以想一想为什么(其实我也没搞懂但是这行代码太好背了) 
    49                 q.push(tr[now].son[i]);
    50             } else{
    51                 tr[now].son[i]=tr[tr[now].fail].son[i];
    52             }
    53         }
    54     }
    55 }
    56 inline void Find(string s){
    57     int len=s.length(),now=0,tmp;
    58     for(int i=0;i<len;i++){
    59         tmp=s[i]-'a';
    60         now=tr[now].son[tmp];
    61         for(int j=now;j;j=tr[j].fail){
    62             ans[tr[j].ed].ct++;//找完一个单词记到ans里 
    63         }
    64     }
    65 }
    66 int main(){
    67       while(114514){//这里可能有点臭 
    68         cin>>n;
    69         if(n==0)break;
    70         Clear(0);
    71         cnt=0;
    72         for(int i=1;i<=n;i++){
    73             cin>>ss[i];
    74             ans[i].ct=0;//这句话害我WA半天 
    75             ans[i].idx=i;
    76             Insert(ss[i],i);
    77         }
    78         Fail();
    79         cin>>ss[0];
    80         Find(ss[0]);
    81         sort(ans+1,ans+n+1,cmp);
    82         //输出结果 
    83         cout<<ans[1].ct<<endl;
    84         cout<<ss[ans[1].idx]<<endl;
    85         for(int i=2;i<=n;i++){
    86             if(ans[i].ct==ans[i-1].ct){
    87                 cout<<ss[ans[i].idx]<<endl;
    88             }else break;
    89         }
    90         //////////
    91     }
    92     return 0;//功德園满 
    93 }
    内容来自_ajhfff_的博客(https://www.cnblogs.com/juruoajh/),未经允许,不得转载。
  • 相关阅读:
    时间复杂度为O(1)的Iveely搜索缓存策略
    数据挖掘十大算法决策树的实现
    编写有效的C# 代码(一)
    数据挖掘十大算法Kmeans之图像区域选择
    asp.net 导出 Excel
    使用XMLSpyDocEditPlugIn2.dll,页面加载失败
    多线程Thread的使用,并使用Thread传参
    ajaxpro.2.dll的使用
    论道WP(二):如何学习WP开发?
    IList<T> 转换成 DataSet
  • 原文地址:https://www.cnblogs.com/juruoajh/p/12238826.html
Copyright © 2020-2023  润新知