AC自动机模板

来源:互联网 发布:网络销售法律法规 编辑:程序博客网 时间:2024/05/29 16:17
#include <cstdio>#include <algorithm>#include <cmath>#include <queue>#include <algorithm>#define N 500006using namespace std;char st[1000005];char keyword[55];int n,m;int next[N][26],cnt[N],fail[N],pos;//初始化字典树的节点int newNode ( ){    for ( int i  = 0; i < 26 ; i++ ) next[pos][i] = 0;    fail[pos] = cnt[pos] = 0;    return pos++;}//构建字典树void insert ( char *s ){    int i,p = 0;//p当前为根节点,i为字符串初始位置    for ( i = 0 ; s[i] ; i++ )    {        //获得这一字母的节点,如果不存在,创建新的        int k = s[i] -'a' , &x = next[p][k];        p = x?x : x = newnode();    }    cnt[p]++; // 位运算要用}//通过宽搜构建失败指针void makeNext ( ){    int i;    queue<int> q;    q.push(0); // 将根节点放入队列中    while ( !q.empty() )    {        int u = q.front();        //统计匹配到当前位置能够匹配到的串的个数        cnt[u] += cnt[fail[u]];        q.pop ();        for ( int i = 0 ; i < 26 ; i++ )        {            int v = next[u][i];            //如果v是0,证明不能匹配,所以通过fail指针找到深度小于当前深度但            //是深度最大的与v和自身的最近公共祖先相邻的与v具有相同字母的节点            //需要通过fail指针跳转过去            if ( v == 0 ) next[u][i] = next[fail[u]][i];            else q.push (v);            //否则,要将v推到队列中去,用于宽搜             if ( u && v )                fail[v] = next[fail[u]][i];        }    }}int query ( char *s ){    int ret = 0, idx , d = 0;    for ( int i = 0; s[i]; i++ )    {        idx = s[i] -'a';        d = next[d][idx];        //将当前位置作为串的结尾能匹配到的串的个数        ret += cnt[d];        //将串的个数清0,避免重复统计        cnt[d] = 0;    }    return ret;}

0 0
原创粉丝点击