zoukankan      html  css  js  c++  java
  • ac自动机俩模板

    ac自动机算法正确性还没有理解,算法导论也看不懂。。等懂了回来发算法专题。

     1 #include <cstdio>
     2 #include <cstring>
     3 using namespace std;
     4 
     5 const int maxn=1e6+5;
     6 
     7 int n;
     8 char s[maxn];
     9 
    10 class AC{
    11 public:
    12     struct node{
    13         node *son[26], *fail;
    14         int mark;
    15     }root, *now, *nowson, *p;
    16     AC(){}
    17     void insert(char *s, int len){ //trie,没什么好说的
    18         now=&root;
    19         int v;
    20         for (int i=0; i<len; ++i){
    21             v=s[i]-'a';
    22             if (!now->son[v]) now->son[v]=new node();
    23             now=now->son[v];
    24         }
    25         ++now->mark;
    26     }
    27     void get_fail(){ //建立失败指针
    28         int head=0, tail=1;
    29         q[head]=&root;
    30         while (head<tail){ //宽搜
    31             now=q[head];
    32             for (int i=0; i<26; ++i) //遍历每个儿子
    33             if (now->son[i]){
    34                 for (p=now->fail; p&&!p->son[i]; p=p->fail); //通过父亲来找失败指针
    35                 //p是0,意味着连root都不行,那只能去root
    36                 now->son[i]->fail=(p?p->son[i]:&root);
    37                 q[tail++]=now->son[i];
    38             } //else now->son[i]=now->fail->son[i]; //如果没有这个子节点,意味着肯定失配
    39             ++head;
    40         }
    41     }
    42     int count(char *s, int len){ //计算有多少个串出现
    43         int ans=0;
    44         now=&root;
    45         int v;
    46         for (int i=0; i<len; ++i){
    47             //确定适配的树的结点位置
    48             for (v=s[i]-'a'; now&&!now->son[v]; now=now->fail);
    49             now=now?now->son[v]:&root; //如果一直到根还不匹配,那就跳到根
    50             //对于一个匹配串的所有后缀检查
    51             //如果这里ans没设置为-1,那就是求出现次数之和
    52             for (p=now; p&&~p->mark; p=p->fail) {
    53                 ans+=p->mark;
    54                 p->mark=-1;
    55             }
    56         }
    57         return ans;
    58     }
    59 private:
    60     node *q[maxn], head, tail;
    61 };
    62 
    63 AC ac;
    64 
    65 int main(){
    66     scanf("%d", &n);
    67     for (int i=0; i<n; ++i){
    68         scanf("%s", s);
    69         int t=strlen(s);
    70         ac.insert(s, t);
    71     }
    72     ac.get_fail();
    73     scanf("%s", s);
    74     printf("%d
    ", ac.count(s, strlen(s)));
    75     return 0;
    76 }
      1 #include <cstdio>
      2 #include <cstring>
      3 using namespace std;
      4 
      5 const int maxn=155, maxl1=75, maxl2=1e6+5;
      6 
      7 int n, cnt, ans[maxn];
      8 char p[maxn][maxl1];
      9 char t[maxl2];
     10 
     11 struct node{
     12     node *son[26], *fail;
     13     int id, mark;
     14 }*mem[maxn*maxl1];
     15 class AC{
     16 public:
     17     node *root, *now, *nowson, *p;
     18     AC(){ root=new node(); }
     19     void fresh(){
     20         cnt=0;
     21         delete root;
     22         root=new node();
     23         for (int i=0; i<memlen; ++i) delete mem[i];
     24         memlen=0;
     25     }
     26     void insert(char *s, int len){ //trie,没什么好说的
     27         now=root;
     28         int v;
     29         for (int i=0; i<len; ++i){
     30             v=s[i]-'a';
     31             if (!now->son[v]) {
     32                 now->son[v]=new node();
     33                 mem[memlen++]=now->son[v];//内存回收表
     34             }
     35             now=now->son[v];
     36         }
     37         //如果不去重,这里写成等于1
     38         now->id=cnt++;
     39         ++now->mark;
     40     }
     41     void get_fail(){ //建立失败指针
     42         int head=0, tail=1;
     43         q[head]=root;
     44         while (head<tail){ //宽搜
     45             now=q[head];
     46             for (int i=0; i<26; ++i) //遍历每个儿子
     47             if (now->son[i]){
     48                 for (p=now->fail; p&&!p->son[i]; p=p->fail); //通过父亲来找失败指针
     49                 //p是0,意味着连root都不行,那只能去root
     50                 now->son[i]->fail=(p?p->son[i]:root);
     51                 q[tail++]=now->son[i];
     52             } //else now->son[i]=now->fail->son[i]; //如果没有这个子节点,意味着肯定失配
     53             ++head;
     54         }
     55     }
     56     void count(char *s, int len){ //计算有多少个串出现
     57         now=root;
     58         int v;
     59         for (int i=0; i<len; ++i){
     60             //确定适配的树的结点位置
     61             for (v=s[i]-'a'; now&&!now->son[v]; now=now->fail);
     62             now=now?now->son[v]:root; //如果一直到根还不匹配,那就跳到根
     63             //对于一个匹配串的所有后缀检查
     64             //如果这里ans没设置为-1,那就是求出现次数之和
     65             for (p=now; p&&~p->mark; p=p->fail) {
     66                 ans[p->id]+=p->mark;
     67                 //p->mark=-1;
     68             }
     69         }
     70     }
     71 private:
     72     node *q[maxn*maxl1]; //这里忘记加了
     73     int memlen;
     74 };
     75 
     76 AC ac;
     77 
     78 int main(){
     79     scanf("%d", &n);
     80     while (n){
     81         memset(ans, 0, sizeof(ans));
     82         for (int i=0; i<n; ++i){
     83             scanf("%s", p[i]);
     84             int t=strlen(p[i]);
     85             ac.insert(p[i], t);
     86         }
     87         ac.get_fail();
     88         scanf("%s", t);
     89         ac.count(t, strlen(t));
     90         int maxm=0;
     91         for (int i=0; i<n; ++i)
     92             if (ans[i]>maxm) maxm=ans[i];
     93         printf("%d
    ", maxm);
     94         for (int i=0; i<n; ++i)
     95             if (ans[i]==maxm) printf("%s
    ", p[i]);
     96         scanf("%d", &n);
     97         ac.fresh();
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    局部变量、结构体和main函数
    类、对象和方法
    Archiver 浅析
    NSArry的常见方法
    iOS 键盘隐藏
    //获取拼音首字母
    UI通过UISlider编写游戏第六感
    UI中各种手势的使用点击,捏合,清扫,旋转,平移,边缘移动,长按
    IOS学习笔记 -- Modal和Quartz2D
    多控制器管理练习 -- 私人通讯录
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/7513545.html
Copyright © 2011-2022 走看看