UESTC 1705 咸鱼钟大爷 随机化+哈希

来源:互联网 发布:安卓模拟器for mac版 编辑:程序博客网 时间:2024/05/10 03:50

咸鱼钟大爷

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
钟望大爷刚刚学习了字符串的哈希算法,对于字符串哈希,他使用的哈希函数是hash[i]=(hash[i-1]*p+ASCII(s[i]))%mod;比如对于p = 2,mod = 1000时,hash('ab') = 97 * 2 + 98 = 292;他认为这样的哈希方法是很难发生冲突的。正巧,这个函数被周日天看到了,周日天劈头盖脸的就是一顿批判,然后扬长而去。留下了钟望大爷在原地一脸懵逼。
现在,对于给出的p,mod,钟望大爷希望你能构造出两个不同字符串(字符串长度不能大于1,000,000且只能由小写字母构成),使得他们的哈希值在这个哈希函数中相同。


Input

输入包括2个正整数p,mod。(0 < p < mod <= 1,000,000,000);


Output

对于每组数据,输出占2行,输出任意一对满足条件的不同的字符串(字符串长度不能大于1,000,000且只能由小写字母构成)。


Sample input and output

Sample Input Sample Output
1 2                                    a

                                          c


Hint

两个字符串的长度可以不同!!!!!


Source

2017 UESTC Training for Search Algorithm & String

UESTC 1705 咸鱼钟大爷


My Solution

题意:给出一个p和mod,求出一对哈希冲突的字符串(长度可以不同)

随机化+哈希
随机生成字符串,然后哈希,然后判断f[hashval]是否出现过,如果出现过就找到了哈希冲突的字符串。
如果枚举到MAXN还是没有找到就换一个哈希种子重新找,这里由于oj把ctime禁用了,
所以可以每次定义一个变量,然后用这个变量的地址作为哈希种子。
关于可以使用随机化的原因,请搜索“生日攻击”百科,里面有详细证明。
复杂度 O(n)


#include <iostream>#include <cstdio>#include <cstring>#include<cstdlib>#include <algorithm>#include <map>using namespace std;typedef long long LL;const int MAXN = 1e6;LL p, MOD;char s[MAXN+8];inline LL mod(LL x){    return x - x / MOD * MOD;}inline int getASCII(int i){    s[i] = char(rand()%26 + 'a');    return int(s[i]);}map<LL, int> mp;int main(){    #ifdef LOCAL    freopen("h.txt", "r", stdin);    //freopen("h.out", "w", stdout);    int T = 4;    while(T--){    #endif // LOCAL    //ios::sync_with_stdio(false); cin.tie(0);    scanf("%lld%lld", &p, &MOD);    bool ans = false;    int i, ind, cnt = 0;    while(true){        if(ans) break;        mp.clear();        LL hashv, last;        cnt+=19;        cnt = max(cnt, 1);        srand(int(&hashv) + cnt);        last = mod(getASCII(0));        mp[last] = 0;        for(i = 1; i < MAXN; i++){            hashv = mod(last*p+getASCII(i));            //printf("%s\n", s);            if(mp.find(hashv) != mp.end()){                s[i+1] = '\0';                printf("%s\n", s);                s[mp[hashv]+1] = '\0';                printf("%s\n", s);                ans = true;                //cout << hashv << " " << hashmap[ind] << endl;                break;            }            last = hashv;            mp[last] = i;        }    }    #ifdef LOCAL    cout << endl;    }    #endif // LOCAL    return 0;}


  Thank you!

                                                                                                                                            ------from ProLights