序列自动机:
序列自动机是一个可以快速判断字符串t是否是字符串s的子串的一个算法。
代码:
nx[i][j]:表示从第i个位置起,字符j出现的第一个位置
int n=strlen(s);
for(int i=0;i<26;i++) nx[n][i]=INF;
for(int i=n-1;i>=0;i--)
{
for(int j=0;j<26;j++) nx[i][j]=nx[i+1][j];
nx[i][s[i]-'a']=i;
}
查询:
我们让pos=-1开始,不断往前跳,如果跳到INF就是找不到下一个字符了,说明t不是s的子串
int find(char ch[])
{
int n=strlen(ch);
int pos=-1;
for(int i=0;i<n;i++)
{
pos=nx[pos+1][ch[i]-'a'];
if(pos==INF) return 0;
}
return 1;
}
模板代码
题目:
https://nanti.jisuanke.com/t/38232
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N=1e5;
int nx[N][26]; //代表从第i个位置开始,字符j出现的第一个 位置
char s[N];
char ch[N];
void init()
{
int n=strlen(s);
for(int i=0;i<26;i++) nx[n][i]=INF;
for(int i=n-1;i>=0;i--)
{
for(int j=0;j<26;j++) nx[i][j]=nx[i+1][j];
nx[i][s[i]-'a']=i;
}
}
int find(char ch[])
{
int n=strlen(ch);
int pos=-1;
for(int i=0;i<n;i++)
{
pos=nx[pos+1][ch[i]-'a'];
if(pos==INF) return 0;
}
return 1;
}
int main()
{
scanf("%s",s);
init();
int m;
cin>>m;
while(m--)
{
scanf("%s",ch);
if(find(ch)) puts("YES");
else puts("NO");
}
}