zoukankan      html  css  js  c++  java
  • AC自动机

    KMP+Trie树(AC自动机将两者优点结合起来)

    三者对比下:
    KMP:处理1个模式串和1个文本串匹配问题(引入了一个kmp数组)
    Trie树:查询n个前缀或者单词在一个字典【n个单词所组成的】里的出现问题 (引入一个特别的Trie树)
    AC自动机:给定n个模式串和1个文本串,查询模式串在文本串里出现问题 (引入了在一个fail数组【即Trie树上的kmp数组】)

    那么这个新引入的fail数组是什么:
    看张动图就明白

    摘自:大佬ppt

    http://files.cnblogs.com/files/crazyacking/AC%E8%87%AA%E5%8A%A8%E6%9C%BA%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8.ppt 

     

     fail数组记录的是:(fa[i]是i的父节点)

    假如第i号节点与fa[i]节点连边值为x,那么从fa[i]节点向上不断fa[i]=fail[fa[i]],直到发现j=fa[i]号节点存在一条与其儿子连边值为x为止,最后令fail[i]=j即可
    但代码实现方式是个反的,也就是说研究对象是u=fa[i]如果发现trie[u][x]=0,那么直接赋值trie[u][x]=trie[fail[u]][x],提前上升为下面子节点服务,否则直接fail[trie[u][x]]=trie[fail[u][x]]赋值即可

    AC自动机代码实现分三个部分:
    void insert(char *s) //向Trie树中插入一个模式串
    void build() //待所有模式串插入后,建立fail数组
    int qry(char *s) //询问文本串在Trie的匹配

    搬运大佬代码:
    https://www.luogu.org/blog/zcysky/solution-p3808

    queue<int>q;
    struct Tree{
    int trie[N][26],sum[N],fail[N],tot=0;
    //插入一个模式串
    void insert(char *s){
    int len=strlen(s),now=0;
    For(i,0,len-1){
    int id=s[i]-'a';
    if(!trie[now][id])trie[now][id]=++tot;
    now=trie[now][id];
    }
    sum[now]++;
    }
    //初始化fail数组
    void build(){
    For(i,0,25)if(trie[0][i])fail[trie[0][i]]=0,q.push(trie[0][i]);
    while(!q.empty()){
    int u=q.front();q.pop();
    For(i,0,25)
    if(trie[u][i])fail[trie[u][i]]=trie[fail[u][i]],q.push(trie[u][i]);
    else trie[u][i]=trie[fail[u]][i];
    }}
    //查询
    int qry(char *s){
    int len=strlen(s),now=0,ans=0;
    For(i,0,len-1){
    now=trie[now][s[i]-'a'];
    for(int t=now;t!=0&&~sum[t];t=fail[t]){
    ans+=sum[t];
    sum[t]=-1;
    }
    return ans;
    }
    }AC;
    
    main:
    For(i,1,n)cin>>str,AC.insert(str);
    AC.build();
    cin>>str;
    cout<<AC.qry(str);
  • 相关阅读:
    TypeScript-基础-09-声明文件
    TypeScript-基础-08-类型断言
    TypeScript-基础-07-函数的类型
    TypeScript-基础-06-数组的类型
    TypeScript-基础-05-对象的类型—接口
    TypeScript-基础-04-联合类型
    TypeScript-工程
    小白学前端03
    小白学前端02
    小白学前端
  • 原文地址:https://www.cnblogs.com/planche/p/9386157.html
Copyright © 2011-2022 走看看