序列自动机

简述

  序列自动机是一个能快速判断一个串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
原文地址:https://www.cnblogs.com/qq2210446939/p/12683119.html