HDU 5972 Regular Number(字符串shift-and算法)
阿新 • • 發佈:2017-09-28
main 鏈接 clu blog include 移動 ref and 運算
題目鏈接 HDU5972
2016 ACM/ICPC 大連區域賽 B題
我們預處理出b[i][j],b[i][j] = 1的意義是數字i可以放在第j位。
然後就開始這個匹配的過程。
假設字符串第一位下標從1開始
我們每一次處理的子串為s[i - n + 1], s[i - n + 2], s[i - n + 3], ..., s[i]
ans[k] = 1的含義是 s[i - k + 1], s[i - k + 2], s[i - k + 3], ..., s[i]這k位可以與t[1], t[2], t[3], t[4],..., t[k]匹配
所以當ans[n] = 1的時候我們就可以輸出當前這個子串
其中t[]表示輸入的那張表。
每次處理的時候,我們先把ans往右移動一位,然後把ans[1]設成1.
但是這樣是不夠的,這相當於把原來那個子串的最前面那位去掉了,我們還要加入最高位。
所以這個時候的ans還要和b[num]進行與運算。(num為新的最高位)
於是這樣一位位處理過去就可以了。
用bitset優化,輸出的時候用字符串輸出,不然會超時。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 5000010; const int M = 1002; bitset <M> b[11]; int n; char s[N]; int main(){ while (~scanf("%d", &n)){ rep(i, 0, 9) b[i].reset(); rep(i, 0, n - 1){ int x; scanf("%d", &x); rep(j, 1, x){ int y; scanf("%d", &y); b[y][i] = 1; } } scanf("%s", s); bitset <M> ans; for (int i = 0; s[i]; ++i){ ans <<= 1; ans[0] = 1; ans &= b[s[i] - ‘0‘]; if (ans[n - 1]){ char tmp = s[i + 1]; s[i + 1] = ‘\0‘; puts(s + i - n + 1); s[i + 1] = tmp; } } } return 0; }
HDU 5972 Regular Number(字符串shift-and算法)