[BZOJ 3752]Hack

暴力Hash

寻找字符串Hash值相同的字典序最小的字符串


完全自己写= =好费劲


2016-3-5 test


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mod 13331
using namespace std;

int P, L, K, len;

struct PD{
	char c[10];
	int len;
	bool operator < (const PD& k)const{
		for(int i = 1; i <= min(len, k.len); i ++){
			if(c[i] < k.c[i])return true;
			else if(c[i] > k.c[i])return false;
		}
		if(len < k.len)return true;
		return false;
	}
	
	bool operator == (const PD& k)const{
		if(len != k.len)return false;
		for(int i = 1; i <= len; i ++)
		    if(c[i] != k.c[i])return false;
		return true;
	}
	
	void operator += (const PD& k){
		for(int i = len + 1; i <= k.len + len; i ++)
		    c[i] = k.c[i - len];
		len += k.len;
	}
	
	bool empty(){
		return len == 0;
	}
	
	void clear(){
		for(int i = 1; i <= len; i ++)
		    c[i] = 0;
		len = 0;
	}
	
	void read(){
		len = 0;
		char QAQ = getchar();
		for(; QAQ < '!'; QAQ = getchar());
		for(; QAQ > '!'; QAQ = getchar())
			c[++ len] = QAQ;
	}
	
	void print(){
		for(int i = 1; i <= len; i ++)
		    putchar(c[i]);
		putchar('\n');
	}
}TMP1, TMP2, test, Ans, c;

struct HashMap{
	#define maxn 1000010
	#define mod 13331
	#define lc i << 1
	#define rc i << 1 | 1
	unsigned val[maxn];
	int h[mod + 10], nxt[maxn], n, size;
	PD ans[maxn];
	void insert(PD cur, unsigned v){
		unsigned tmp = v % mod;
		for(int i = h[tmp]; i; i = nxt[i]){
			if(val[i] == v){
				if(cur < ans[lc]){
					ans[rc] = ans[lc];
					ans[lc] = cur;
				}
				else if(ans[rc].empty() || cur < ans[rc])
					ans[rc] = cur;
				return;
			}
		}
		int newnode = ++ size;
		val[newnode] = v;
		nxt[newnode] = h[tmp];
		h[tmp] = newnode;
		ans[newnode << 1] = cur;
	}
	
	void pushup(const PD& k){
		if(TMP1.empty()){
			TMP1 = k;
			return;
		}
		if(k < TMP1){
			TMP2 = TMP1;
			TMP1 = k;
			return;
		}
		if(TMP2.empty() || k < TMP2)
		    TMP2 = k;
	}
	
	bool ask(unsigned v){
		unsigned tmp = v % mod;
		for(int i = h[tmp]; i; i = nxt[i]){
			if(val[i] == v){
				//TMP1 = ans[lc];TMP2 = ans[rc];
				if(!ans[lc].empty())pushup(ans[lc]);
				if(!ans[rc].empty())pushup(ans[rc]);
				return true;
			}
		}
		return false;
	}
	
}dp[5];
int UP;
void DFS_pre(int dep, unsigned hash){
	if(dep == UP)return;
	for(int i = 'A'; i <= 'Z'; i ++){
		test.c[dep] = i;
		test.len = dep;
		dp[dep].insert(test, hash * P + i);
		DFS_pre(dep + 1, hash * P + i);
	}
	test.c[dep] = 0;
}

unsigned Hash[10], need;

bool find(int dep, unsigned hash){
	if(dep > L)return false;
	if(hash == need && !(Ans == test))return true;
	if(L - dep <= 4){
		int up = L - dep;
		bool flag = false;
		for(int i = 1; i <= up; i ++){
            unsigned h = hash * Hash[i];
            h = need - h;
            flag |= dp[i].ask(h);
		}
		if(flag){
			c = Ans;
			Ans += TMP1;
			if(Ans == test){
				if(TMP2.empty())return false;
				c += TMP2;
				Ans = c;
			}
		}
		flag &= !Ans.empty();
		return flag;
	}
	for(int i = 'A'; i <= 'Z'; i ++){
		Ans.len = dep + 1;
		Ans.c[dep + 1] = i;
		if(find(dep + 1, hash * P + i))return true;
	}
	return false;
}

int main(){
	//freopen("hack.in", "r", stdin);
	//freopen("hack.out", "w", stdout);
	
	scanf("%d%d%d", &P, &L, &K);
	UP = min(L + 1, 5);
	DFS_pre(1, 0);
	
	Hash[0] = 1;
	for(int i = 1; i <= L; i ++)
		Hash[i] = Hash[i - 1] * P;
		
	for(int i = 1; i <= K; i ++){
		test.read();
		TMP1.clear();
		TMP2.clear();
		Ans.clear();
		c.clear();
		need = 0;
		for(int j = 1; j <= test.len; j ++)
		    need = need * P + test.c[j];
		if(find(0, 0) == false)
		    printf("-1\n");
		else Ans.print();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值