zoukankan      html  css  js  c++  java
  • [USACO5.1]乐曲主题Musical Themes

    https://www.luogu.org/problemnew/show/P2743

    第一次写双哈希

    提供一个也许能过n <= 20000的哈希做法

    常规套路,我们求出原串哈希值,然后二分答案mid,依次枚举每个位置起始,长为mid的串是否出现过,然后用map维护串的上一次的开始位置,复杂度O(nlog^2n)

    对于转调,处理原数组的差分数组即可

    然后这里有一个问题,哈希值容易重复。根据某(其实是我忘了叫啥的概率模型):值域在[0,mod]的哈希值,对于[0,20000]次的询问,冲突的概率其实很大,只是因为luogu上数据小,所以能过

    解决这一问题的方法是双哈希。选择两个模数作为哈希,开两个map分别维护两个哈希值,map里维护<ll,pair>,pair里存位置和这个点的另一个哈希值。然后在算某个位置的哈希值的时候呢,你将两个哈希值都算出来,哪个能够和两个都匹配上,哪个就是正确的

    这样的出错概率就很小了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cmath> 
    #include<iostream>
    #include<map>
    using namespace std;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << "  ";
    #define B cout << "breakpoint" << endl;
    #define pii pair<ll,int>
    #define mp make_pair
    typedef double db;
    typedef long long ll;
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch  = getchar();
        }
        return ans * op;
    }
    const int maxn = 5005;
    const ll b = 5205;
    const ll mod0 = 998244353;
    const ll mod1 = 19260817;
    ll hash[maxn][2],base[maxn][2];
    int a[maxn],val[maxn];
    int n;
    bool check(int l)
    {
        l--;
        map<ll,pii> m0,m1;
        for(int i = 1;i <= n - l;i++)
        {
            ll tp0 = (hash[i + l - 1][0] - hash[i - 1][0] * base[l][0] % mod0 + mod0) % mod0;
            ll tp1 = (hash[i + l - 1][1] - hash[i - 1][1] * base[l][1] % mod1 + mod1) % mod1;
            if(m0[tp0].second)
            {
                pii u0 = m0[tp0];
                ll val0 = u0.first,lt = u0.second;
                if(val0 == tp1 && i - lt >= l + 1) return 1;
            }
            if(m1[tp1].second)
            {
                pii u1 = m1[tp1];
                ll val1 = u1.first,lt = u1.second;
                if(val1 == tp0 && i - lt >= l + 1) return 1;
            }
            if(!m1[tp1].second && !m0[tp0].second) 
            {
                m0[tp0] = mp(tp1,i);
                m1[tp1] = mp(tp0,i);
            }
        }
        return 0;
    }
    int main()
    {
        n = read();
        base[0][0] = base[0][1] = 1;
        for(int i = 1;i <= n;i++)
            val[i] = read();
        for(int i = 1;i < n;i++)
        {
            a[i] = val[i + 1] - val[i] + 88;
            base[i][0] = (base[i - 1][0] * b) % mod0;
            hash[i][0] = (hash[i - 1][0] * b % mod0 + (ll)a[i]) % mod0;
            base[i][1] = (base[i - 1][1] * b) % mod1;
            hash[i][1] = (hash[i - 1][1] * b % mod1 + (ll)a[i]) % mod1;
        }
        int l = 5,r = n;
        int ans = 0;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(check(mid))
                l = mid + 1,ans = max(ans,mid);
            else r = mid;
        }
        printf("%d",ans);
    }
            
    View Code
  • 相关阅读:
    zookeeper集群搭建
    Redis集群管理
    postman的使用
    python接口自动化:requests+ddt+htmltestrunner数据驱动框架
    python实现建立websocket通信
    python实现建立soap通信(调用及测试webservice接口)
    python接口自动化:响应内容中json字符串对象的处理
    python接口自动化:调试接口的代码(无token情况下)
    python接口自动化:https请求,取消警告
    python接口自动化:对外接口sign签名
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10907522.html
Copyright © 2011-2022 走看看