Loading

子序列自动机

子序列自动机

1 简介

子序列自动机可以解决多次子串匹配。

给定一个字符串 \(t\) ,一共有 \(q\) 次询问,每次给定另外一个字符串 \(s\) ,询问 \(t\)\(s\) 中出现了多少次。

我们跑 \(q\) 遍 KMP 就可以了。如果我们把这道题改成子序列匹配呢?

于是就有了这道题

2 做法

对于每一种字符,我们开一个数组记录一下它在那些地方出现过,然后对于待匹配串的所有字符,一一匹配,保证位置比上一次的位置靠后,我们查找时可以使用二分,这样就可以了。

时间复杂度为 \(O(len(S)+\log len(S)\times \sum len(T))\)

代码:

int type,n,q,m,a[N],b[N];
vector<int> v[N];

int main(){
    type=read(),n=read(),q=read(),m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
        v[a[i]].push_back(i);
    }
    for(int i=1;i<=q;i++){
        int l=read(),last=0;bool op=1;
        for(int j=1;j<=l;j++) b[j]=read();
        for(int j=1;j<=l;j++){
            vector<int>::iterator it=upper_bound(v[b[j]].begin(),v[b[j]].end(),last);
            if(it==v[b[j]].end()){
                op=0;break;
            }
            last=*it;
        }
        if(op) printf("Yes\n");
        else printf("No\n");
    }
}
posted @ 2021-04-19 19:55  hyl天梦  阅读(98)  评论(0编辑  收藏  举报