必威体育Betway必威体育官网
当前位置:首页 > IT技术

【AC自动机】拓扑优化

时间:2019-09-25 20:14:29来源:IT技术作者:seo实验室小编阅读:79次「手机版」
 

拓扑优化

  • 之前文章中的AC自动机的劣势:要么只能一次跳fail,无法更新所有fail指的点(如图1),要么fail只能一次跳一格(如图二),更新速度最慢可以卡到O(文本串长度*trie树深度)。

  • 优化目的:防止每次到一个点时就更新所有fail的点,大大节省时间
  • 思路:在原来的模板上增加每个点的入度(有几个fail指针指着自己),在最后一次性更新(其实就是用fail指针建边的拓扑),新增内容详见代码
  • 例题:洛谷 p5357

代码:

#include<bits/stdc++.h>
using namespace std;
struct tree{
    int zz[27],fail,val,jl,rd;//rd为入度,jl为记录,记录走过此点的次数,用来统计单词数
}trie[200005];
char st[2000005];
int tot,ans=0,m[200005];//m位标记,m[i]=p 意为单词i的结尾在字典树的p位
void build(int l,int id)
{
    int p=0;
    for(int i=0;i<l;i++)
    {
        if(!trie[p].zz[st[i]-'a'])
        {
        	trie[p].zz[st[i]-'a']=++tot;
        }
        p=trie[p].zz[st[i]-'a'];
    }
    trie[p].val=1;
    m[id]=p;//结尾标记
}
void iflose()
{
    int sj,sjs;
    queue<int> q;
    for(int i=0;i<26;i++)
    {
        if(trie[0].zz[i])
        q.push(trie[0].zz[i]);
    }
    while(!q.empty())
    {
        sj=q.front();
        q.pop();
        for(int v,i=0;i<26;i++)
        {
            sjs=trie[sj].zz[i];
            if(sjs==0)
            continue;
            v=trie[sj].fail;
            while(v&&!trie[v].zz[i])v=trie[v].fail;
            if(trie[v].zz[i]!=sjs)
            {
                trie[sjs].fail=trie[v].zz[i];
                trie[trie[v].zz[i]].rd++;         //增加入度
            }
            if(trie[sj].zz[i])
            {
                q.push(trie[sj].zz[i]);
            }
        }
    }
}
void check()
{
    int len=strlen(st),p=0;
    for(int i=0;i<len;i++)
    {
    	while(!trie[p].zz[st[i]-'a']&&p!=0)p=trie[p].fail;
        p=trie[p].zz[st[i]-'a'];
        if(!p)continue;
        trie[p].jl++;
    }
}
queue<int>q;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",st);
        build(strlen(st),i);
    }
    iflose();
    scanf("%s",st);
    check();
    for(int i=1;i<=tot;i++)
    if(trie[i].rd==0)
    q.push(i);               //将所有入度为0的点压进栈
    int sj;
	while(!q.empty())
    {
    	sj=q.front();q.pop();
    	trie[trie[sj].fail].jl+=trie[sj].jl;//给自己的失配指针所指的点x更新
    	trie[trie[sj].fail].rd--;           //删去这条fail边
    	if(trie[trie[sj].fail].rd==0)       //如果删后x入度为0
    	q.push(trie[sj].fail);              //压入栈
    }
    for(int i=1;i<=n;i++)
    printf("%d\n",trie[m[i]].jl);
    return 0;
}

相关阅读

ROI 的优化,其实是场足球赛

ROI的优化就像一场足球赛,需要根据市场条件,制定合理的战术布局,搭配不同的渠道,才能更大几率赢得比赛。ROI很重要。重要到,很多公司把

小米路由器下线“自动重启”:是为了上线“路由自动优化

A5创业网(公众号:iadmin5)1月22日消息,近日,小米路由器下线了&ldquo;自动重启&rdquo;功能,被不少用户吐槽。小米路由器官方微博称,此次

用HMW法分析:如何优化享物说的社交效果

享物说(小程序)作为一个好物互送的平台,越来越多的人在“单纯物品交换”环境下产生了很多互动。本文用HMW法分析,如何优化享物说这一

淘宝直通车怎么优化点击率?有哪些方法?

淘宝直通车是一个帮助在淘宝开店的商家们进行推广的一个工具,当然使用它是需要付费的,那么它到底有哪些功能呢?如何使用淘宝直通车

斗鱼人事动荡 紧急裁员70余人 斗鱼回应:正常的优化调整

A5创业网(公众号:iadmin5)12月6日消息,最近斗鱼陷入了裁员风波。约70位斗鱼(香港)有限公司被公司裁员,斗鱼回应称正常的优化调整,但不

分享到:

栏目导航

推荐阅读

热门阅读