• 序列自动机


    简述

      序列自动机是一个能快速判断一个串t是否为另一个串s的子序列的算法。对于串s构造序列自动机,本质上就是预处理出一个nxt[][]数组,nxt[i][j]代表从第i个位置开始,字符j出现的第一个位置的下一个位置。

    代码详解

    构造

      复杂度O(lens)

      对于nxt数组的构造本质上就是一个dp的过程,len位置就是最后一个位置+1,所以我们设置一个末边界为inf,往前递推对于之后的每个位置该位置的字符的nxt值就是i+1,其他字符就是nxt[i+1]的值。

    void init(char *s){
        int len=strlen(s);
        for(int i=0;i<26;i++) nxt[len][i]=inf;
        for(int i=len-1;i>=0;i--){
            for(int j=0;j<26;j++){
                nxt[i][j]=nxt[i+1][j];
            }
            nxt[i][s[i]-'a']=i;
        }
    }

     查询

      复杂度O(lent)

      对于串t,我们可以利用nxt数组,pos指针初始化为0,pos就是开始查找的下标,每次令pos=nxt[pos][当前字符],也就是匹配字符的后一个位置=下一个开始找的位置,当pos=inf时证明在pos位置开始后面没有所需字符了,所以不是子序列。

    bool find(char *t){
        int len=strlen(t);
        int pos=-1;
        for(int i=0;i<len;i++){
            pos=nxt[pos+1][t[i]-'a'];
            if(pos==inf) return 0;
        }
        return 1;
    }

    模板

    void init(char *s){
        int len=strlen(s);
        for(int i=0;i<26;i++) nxt[len][i]=inf;
        for(int i=len-1;i>=0;i--){
            for(int j=0;j<26;j++){
                nxt[i][j]=nxt[i+1][j];
            }
            nxt[i][s[i]-'a']=i;
        }
    }
    bool find(char *t){
        int len=strlen(t);
        int pos=-1;
        for(int i=0;i<len;i++){
            pos=nxt[pos+1][t[i]-'a'];
            if(pos==inf) return 0;
        }
        return 1;
    }
    View Code
  • 相关阅读:
    关于MySQL错误 2005
    Eclipse如何导入第三方jar包
    Codeforces Round #377 (Div. 2) D. Exams
    18110 Koishi's travel, Satori's travel
    用Java做的类似皇家守卫战的游戏
    Notepad++如何编译、运行Java
    Codeforces Round #341 (Div. 2)--C. Wet Shark and Flowers
    hdu 2120 Ice_cream's world I
    FZU 1851 组合数
    HUST 1599 Multiple
  • 原文地址:https://www.cnblogs.com/qq2210446939/p/12683119.html
Copyright © 2020-2023  润新知