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

129 篇文章 0 订阅
117 篇文章 2 订阅

咸鱼钟大爷

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值