Shift-And / Shift-Or

神妙的战法!

先介绍Shift-And

Task:在s中里找t

做法

遍历s,采访到s的第i位的时候,用bitset记录t中哪些前缀,是s.substr(1,i)的后缀。

如果在这个bitset中第j位为1

那么:

  • s[i] = t[j]
  • j-1位,在采访到s的第i-1位的时候,为1

由此,我们推导出从i-1i位,bitset的转移。

for(int i=0;t[i];i++)
    B[t[i]].set(i);
for(int i=0;s[i];i++) {
	D=D<<1, D.set(0);
	D &= B[s[i]];
	//然后就可以为所欲为
}

再来介绍ShiftOr

ShiftAnd中。

转移式为D=(D<<1|1)&B[s[i]],在这里我们将D取反(1代表不在,0代表在)
转移式为D=(D<<1)|B[s[i]]

来看个栗子:HDU5972

Task:匹配,模板串一个位置有多个选择。

shift-or版本

#include <iostream>
#include <bitset>
#include <vector>
#include <cstring>
using namespace std;
const int N = 1002;
vector<int> v[N];
char s[5000000+10];
int n;

void shift_Or() {
    bitset<N> B[10],D;
    for(int i=0;i<10;i++) B[i].set();
    D.set();
    for(int i=0;i<n;i++) {
        for(int j=0;j<v[i].size();j++) 
            B[v[i][j]].reset(i);
    }
    int len = strlen(s);
    for(int i=0;i<len;i++) {
        D = D<<1;
        D |= B[s[i]-'0'];
        if (D[n-1]==0) {
            char tmp = s[i+1];
            s[i+1]='\0'; 
            puts(s+i-n+1);
            s[i+1]=tmp;
        }
    }
}

int main() {
    while (~scanf("%d", &n)) {
        for(int i=0;i<n;i++) {
            v[i].clear();
            int x; scanf("%d", &x);
            for(int j=1;j<=x;j++) {
                int y; scanf("%d", &y);
                v[i].push_back(y);
            }
        }
        scanf("%s", s);
        shift_Or();
    }
}

posted @ 2018-05-23 00:19  RUSH_D_CAT  阅读(687)  评论(0编辑  收藏  举报