1. 程式人生 > >Shift-And / Shift-Or

Shift-And / Shift-Or

OS 推導 reset 遍歷 %d AS ID int strong

神妙的戰法!

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

Shift-And / Shift-Or