暴力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;
}