子序列自动机
子序列自动机
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");
}
}