• 序列自动机入门


    文章发布于摸鱼世界,转载请注明出处。


    前言

    叫什么自动姬嘛,一个数组的事情(bushi


    正文

    吾日三省吾身:

    这玩意有啥用?

    这玩意咋做的?

    这玩意咋写?

    先来看序列自动机是干什么用的。

    看它的名字就知道这和子序列有关,没错,它的基本作用就是快速的查询一个串是否是母串的子序列/母串的子序列个数等问题。当然,拓展的问题我也不会。


    引入一个二维数组(nxt[][])(nxt[i][j])表示第(i)位之后(不含第(i)位)的第一个字符(j)的位置。字符是不能直接作为数组的下标的,所以我们就把它们的(ACSll)码减去其中值最小的字符的值作为下标。比如字符都是'a'-'z',我们就可以把字符减去'a'来作为下标,节省空间。

    但是需要注意的一个细节是要把第0个位置空出来,这是状态的起点。所以输入的时候就用scanf("%s",str+1);即可。

    如果有这样一个数组,我们就可以把每次要判断的串放到自动机里跑,直到全部匹配或是匹配失败。

    那么重点就是如何实现这个nxt数组的维护。

    首先有两个明显的结论。

    1.如果第i位的字符为j,那么有nxt[i-1][j]=i

    2.除了字符j以外的字符集内任意一个字符k,都有nxt[i-1][k]=nxt[i][k]

    我们如果要用这两条规律进行推导的话,因为在2中是要用nxt[i][k]推出nxt[i-1][k],所以循环的时候我们通过逆循环来实现推导就好了。

    下面是这一步的代码块:(字符集'a'-'z')

    void getnext(char str[])
    {
        int len=strlen(str+1);
        for(int i=len;i>=1;i--)
        {
            for(int j=0;j<26;j++)
                c[i-1][j]=c[i][j];
            c[i-1][str[i]-'a']=i;
        }
        return;
    }
    

    接下来还是要说一下查询(一个串是否是母串的子序列)应该如何实现。

    我们只需要像其他自动机(指AC自动机)那样从初始状态(i=0)开始往下循环,每次如果可行,就跳到nxt[i][str[i]-'a'],如果不可行,那么就是不匹配,直接退出循环就好。

    void ask(char str[])
    {
        bool s=1;
        int u=0;
        for(int i=0;str[i];i++)
        {
            u=c[u][str[i]-'a'];
            if(!u)
            {
                s=0;
                break;
            }
        }
        puts(s?"Yes":"No");
    }
    

    最后一个基本操作,求(母串的(不重复的子序列)的个数)的实现。

    把这个自动机看做是一棵树,每条边即为从i出发,连向所有nxt[i][j]。而不重复子序列的个数,只需要统计一下这棵树上的结点个数即可。

    至于为什么?画个图感性理解一下吧我也不会证 ::aru:diving::

    int cnt=0;
    void dfs(int u)
    {
        cnt++;
        for(int i=0;i<26;i++)
            if(c[u][i])dfs(c[u][i]);
    }
    

    (记忆化搜索可以优化时间)


    基础操作就讲到这里,如果以后遇到有趣的题也不来更新就来更新。

    你听到鸽子叫了吗~

  • 相关阅读:
    一次性能测试的面试问题
    一次APP测试的感悟
    《程序员跳槽全攻略》读书笔记
    如果有人让你推荐编程技术书,请叫他看这个列表
    上班的一天
    马士兵Java视频教程 —— 学习顺序
    月薪3万的技术网站资源收集
    给32岁的自己一些答案
    《Vuser虚拟用户开发》读书笔记
    shell脚本异常:/bin/sh^M:bad interpreter: No such file or directory
  • 原文地址:https://www.cnblogs.com/moyujiang/p/12694740.html
Copyright © 2020-2023  润新知