【笔记】Shift-And算法&Shift-OR算法
Shift-And
S表示原串,T表示目标串,要在S中搜索T
D是一个bitset:D[n-1,n-2,...,1,0]共n位
x控制S串的扫描,当扫描到字符S[x]时,D的第y位D[y]=1当且仅当T[0..y]是S[0..x]的一个后缀
B是一个map,key是题目字符集合,value是一个bitset,记录该字符在模式串T的哪些位置出现
例如,字符c 在T[2] 处出现,那么B['c'] = 000100 (对于字符串,低位在左;对于B['c'],低位在右);同理,a 在T[0],T[3] 处出现,B['a'] = 001001.
初始D[0]=1当且仅当S[i]=T[0]
假设当前处理到S[x],需要对D进行更新,D[j]=1当且仅当D[j-1]==1&&S[i]=T[j]
所以 D=(D<<1|1)&B[s[x]];
Shift-OR
用0表示一个数在集合里,1表示不在
D=(D<<1)|B[s[x];B,D初始化全1
#include<bits/stdc++.h> using namespace std; bitset<1001>B[10]; bitset<1001>D; int n,m; void csh(){ for(int i=0;i<10;i++) B[i].set(); D.set(); } char s[5000005]; void output(int x){ int be = x-n+1; char tmp = s[x+1]; s[x+1]='\0'; puts(s+be); s[x+1]=tmp; } void input(){ int x; for(int i=0;i<n;i++){ scanf("%d",&m); while(m--){ scanf("%d",&x); B[x][i]=0; } } scanf("%s",s); m = strlen(s); } void solve(){ for(int i=0;i<m;i++) { D=(D<<1)|B[s[i]-'0']; if(D[n-1]==0)output(i); } } int main(){ while(scanf("%d",&n)!=EOF) { csh(); input(); solve(); } }