zoukankan      html  css  js  c++  java
  • AC自动机【萌新文章】

    我这个蒟蒻第一次写博客,有点小激动呢。

    主要是最近刚学了AC自动机,学得糟糟糕糕,记录一下,看到dalao们都在写博客,决定自己也写一波【我好水的啦,写的也不好】

    AC自动机大概就是    Trie+KMP=AC自动机

    嗯,在KMP中,引入了字符串失配最优转移方案:失配函数f[i],在j位匹配失败后,便转到f[j]位匹配

    同样的道理,AC自动机就是升维的KMP,在匹配时不仅要考虑当前模板串,还要顾及其它模板串,所以失配函数还要顾及其它模板串,匹配成功也要考虑其它模板串

    所以,AC自动机采用了bfs构造f[],还引入了last[]后缀链接,用以指向当前串匹配成功时同时可以匹配成功的串

    具体来讲AC自动机有三个操作

    插入:

    与trie树的插入方式相同

    void insert(int id)
    {
    	int u=0;
    	for(int i=0;i<len[id];i++)
    	{
    		int v=P[i]-'a';
    		if(!ch[u][v])
    		{
    			ch[u][v]=++siz;
    			fill(ch[siz],ch[siz]+26,0);
    		}
    		u=ch[u][v];
    	}
    	val[u]=id;
    }


    构造失配函数:

    这里采用了优化方法,将子节点不存在的子节点指针直接指向f[]函数指向节点的子节点,然后在匹配时甚至可以不用f[]函数,因为在构造时已经提前把匹配不成功时的指向指向了f[]指针,这能节省不少时间。

    总的过程采用bfs构造f[],同时构造last,通过f[]检查是否可以转移

    具体思想与KMP相同

    void getfail()
    {
    	queue<int> q;
    	for(int i=0;i<26;i++) if(ch[0][i]) q.push(ch[0][i]);
    	int u,v;
    	while(!q.empty())
    	{
    		u=q.front();
    		q.pop();
    		for(int i=0;i<26;i++)
    		{
    			v=ch[u][i];
    			if(!ch[u][i])
    			{
    				ch[u][i]=ch[f[u]][i];
    				continue;
    			}
    			q.push(v);
    			f[v]=ch[f[u]][i];
    			last[v]=val[f[v]] ? f[v]:last[f[v]];
    		}
    	}
    }


    匹配:

    
    
    
    
    void AC()
    {
    	vis[0]=true;
    	ans=0;
    	char c=getchar();
    	int id,u=0;
    	while(!isalpha(c)) c=getchar();
    	for(int i=1;isalpha(c);i++)
    	{
    		vis[i]=false;
    		id=c-'a';
    		u=ch[u][id];
    		if(val[u]) print(u);
    		else if(last[u]) print(last[u]);
    		c=getchar();
    	}
    }

    print为沿着last的打印函数


    嗯就这样

  • 相关阅读:
    【NX二次开发】修改dlx对话框标题的方法
    【NX二次开发】导入x_t,UF_PS_import_data
    设置NX欢迎界面
    [转]10个顶级的CSS UI开源框架
    [转] 多线程 《深入浅出 Java Concurrency》目录
    [转] JAVA多线程和并发基础面试问答
    [转]StuQ 技能图谱(全套13张)
    [转] MongoDB shell 操作 (查询)
    搜集好的java技术帖子,持续更新,java程序员的要求
    [转]JAVA程序员一定知道的优秀第三方库(2016版)
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282905.html
Copyright © 2011-2022 走看看