Shift-And / Shift-Or
阿新 • • 發佈:2018-05-23
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-1
到i
位,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