对于每种字符 \(c \in \Sigma\),构造掩码 \(B_c\),其中 \(B_c[i]=[s[i]=c]\)。维护二进制串 \(D\),假设当前文本串扫描到了第 \(i\) 位,则 \(D[j]=1\) 当且仅当模式串的前缀 \(p[1..j]\) 与文本串前缀 \(s[1..i]\) 的长度为 \(j\) 的后缀完全相等。
每次读入一个新字符后,将 \(D\) 左移一位并加上 \(1\),与该位字符对应的掩码按位与,得到新的 \(D\)。
如果存在某次操作后,使得 \(D\) 的最高位是 \(1\),根据定义,即此时文本串当前前缀的长度为 \(|p|\) 的后缀与 \(p\) 完全相同,则 \(i\) 是一个匹配成功的末尾位置。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 10005;
bitset<N> b[N],d;
char s[N],p[N];
int ls,lp;
signed main()
{
ios::sync_with_stdio(false);
cin>>s+1>>p+1;
ls=strlen(s+1);
lp=strlen(p+1);
for(int i=1;i<=lp;i++)
{
b[p[i]][i]=1;
}
for(int i=1;i<=ls;i++)
{
d<<=1;
d[1]=1;
d&=b[s[i]];
if(d[lp]) cout<<i<<" ";
}
}