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();
    }
}