1. 程式人生 > >HDU 5972 Regular Number(字符串shift-and算法)

HDU 5972 Regular Number(字符串shift-and算法)

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算法)