• 长春理工大学第十四届程序设计竞赛D Capture The Flag——哈希&&打表


    题目

    链接

    题意:给定一个字符串 $s$,求不同于 $s$ 的字符串 $t$,使得 $Hash(s) = Hash(t)$,其中 $displaystyle Hash(s) = sum_0^{len-1} x_i imes p^i$,$4 leq p,m leq 10^9$ 且$m$为质数,所有输入输出的字符串内的字符ASCII码的取值范围为 $[31, 126]$.

    分析

    由于最终哈希值会模 $m$,所以最多 $m$ 种哈希值,可以先建立起 $sqrt m$ 个不同哈希值的表。

    具体的,利用枚举3位字符串得到 $(126-31)^3 approx 10^6$个字符串的哈希值,用map存,近似达到 $sqrt m$ 个哈希值。

    先从表中选取一个字符串作为高3位,计算出低3位哈希值应该为多少,在从表中查找这个值,找到一个就退出,最多执行 $10^6$ 次。

    那么单次不击中(没找到)的概率为 $displaystyle frac{m - sqrt m}{m}$,因此连续 $10^6$ 次不击中的概率为 $(frac{m - sqrt m}{m})^{1e6} = 0.00004539$,这个概率非常小,可认为总能找到答案

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    map<int, string>mp;
    vector<ll>vec;
    const int L = 33, R = 136;
    ll p, m;
    string str;
    
    //97^3组哈希值,达到sqrt(m)
    void dfs(int pos, ll v, ll pw, string s)
    {
        if(pos >= 4)
        {
            mp[v] = s;  //hash(s)=v
            vec.push_back(v);
            return;
        }
        for(int i = L;i <= R;i++)  dfs(pos+1, (v + i * pw)%m, (pw * p) % m, s + (char)(i));
    }
    
    //查找哈希值x是否存在
    bool find(ll x)
    {
        auto it = lower_bound(vec.begin(), vec.end(), x);
        return it != vec.end() && (*it == x);
    }
    
    //求hash(s)
    ll Hash(string s)
    {
        ll ans = 0;
        ll pw = 1;
        for(auto ch : s)
        {
            ans += (ll)ch * pw;
            ans %= m;
            pw = pw * p % m;
        }
        return ans;
    }
    
    int main()
    {
        cin >> p >> m >> str;
        ll h = Hash(str);
        //printf("hash: %lld
    ", h);
        
        dfs(1, 0, 1, "");
    
        sort(vec.begin(), vec.end());   //
    
        ll pw = 1;
        for(int i = 1;i <= 3;i++)  pw = pw * p % m;
        for(auto i : vec)
        {
            ll v = (h - (i * pw) % m + m) % m;
            if(find(v))
            {
                //string t=mp[v]+mp[i];
                //printf("hash2: %lld
    ", Hash(t));
                cout << mp[v] << mp[i] << endl;
                return 0;
            }
        }
    }

    参考链接:https://zhuanlan.zhihu.com/p/72702597

  • 相关阅读:
    图解排序算法(三)之堆排序
    博客园添加看板娘
    php设计模式
    PHP二维数组排序 array_multisort
    php-jwt-token
    c++实现冒泡排序
    常见的排序 转
    Mac VMware Fusion CentOS7配置静态IP
    vmwar快照和克隆区别
    springboot maven打包插件
  • 原文地址:https://www.cnblogs.com/lfri/p/11199865.html
Copyright © 2020-2023  润新知