• 字符串hash


    目的:把字符串有效地转化为一个整数,极小的概率会出现两个字符串hash值相等。

    学习链接:https://www.luogu.org/blog/pks-LOVING/zi-fu-chuan-xue-xi-bi-ji-ha-xi-hash-yu-zi-dian-shu-trie#

    hash[i]=(hash[i-1]*p+idx(s[i]))%mod

    hash[l..r]=(hash[r]-hash[l-1]*(p^(r-l+1))+mod)%mod

    自动取模hash:unsigned long long hash[maxn],范围[0, 2^64) ,即mod=2^64

    保险double hash,mod1=1e9+7,mod2=1e9+9,mod1与mod2为孪生素数,冲突概率极低(hash的维度越高,耗时越高,耗内存越大)

    hash1[i]=(hash1[i-1]*p+idx(s[i]))%mod1

    hash2[i]=(hash2[i-1]*p+idx(s[i]))%mod2

    基本操作:二分+hash

    自用模板:

    P3370 【模板】字符串哈希:https://www.luogu.org/problemnew/show/P3370

    #include<bits/stdc++.h>
    using namespace std;
    #define ull unsigned long long
    const int maxn=1e4+10;
    ull base=131,mod=21237044013013795711;
    int prime=233317;
    ull hashe(char *s)
    {
        int len=strlen(s);
        ull ans=0;
        for(int i=0;i<len;i++)
        {
            ans=(ans*base+(ull)s[i])%mod+prime;
        }
        return ans;
    }
    int main()
    {
        int n,ans=1;
        char s[maxn];
        ull a[maxn]={0};
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
            a[i]=hashe(s);
        }
        sort(a+1,a+n+1);
        for(int i=1;i<n;i++)
        {
            if(a[i]!=a[i+1])ans++;
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    P2957谷仓里的回声Barn Echoes:https://www.luogu.org/problemnew/show/P2957,前缀后缀最长公共部分,kmp可做

    #include<bits/stdc++.h>
    #define ull unsigned long long
    using namespace std;
    const int maxn=100;
    ull base=131,mod=21237044013013795711;
    int prime=233317;
    ull hashe(string s)
    {
        int len=s.size();
        ull ans=0;
        for(int i=0;i<len;i++)
        {
            ans=(ans*base+(ull)s[i])%mod+prime;
        }
        return ans;
    }
    
    string s,s2;
    ull a[maxn],a2[maxn];
    int main()
    {
        int ans=0,len;
        cin>>s>>s2;
        len=min(s.size(),s2.size());
        
        for(int i=1;i<=len;i++)
        {
            string tmp1=s.substr(s.size()-i,i),tmp2=s2.substr(0,i);
            if(hashe(tmp1)==hashe(tmp2)&&i>ans)ans=i;
        }
        for(int i=1;i<=len;i++)
        {
            string tmp1=s2.substr(s2.size()-i,i),tmp2=s.substr(0,i);
            if(hashe(tmp1)==hashe(tmp2)&&i>ans)ans=i;
        }
        
        printf("%d
    ",ans);
        return 0;
    } 
    View Code

    P1381单词背诵:https://www.luogu.org/problem/P1381,n个单词要背,m个单词序列,选一段序列使得包含要背诵的单词num越多越好,num相等时序列长度len越短越好,输出num和len。单词用hashe处理,方法为O(n)复杂度的尺取,刚开始wa在越多越好这个点,其实这个数num是可算的,m个单词里滚一边出现过几种要背的单词就好了。可能没出现过,这种情况放到while里不能跳出循环,因为sum和num始终为0,所以需要特判。

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define ull unsigned long long
    using namespace std;
    const int maxn=1e5+10;
    ull base=131,mod=21237044013013795711;
    int prime=233317;
    ull hashe(char *s)
    {
        int len=strlen(s);
        ull ans=0;
        for(int i=0;i<len;i++)
        {
            ans=(ans*base+(ull)s[i])%mod+prime;
        }
        return ans;
    }
    map<ull,int> appear,mp,vis;
    ull cnt[maxn];
    int main()
    {
        int n,m,num=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            char s[20];
            scanf("%s",s);
            ull tmp=hashe(s);
            appear[tmp]=1;
        }
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            char s[20];
            scanf("%s",s);
            ull tmp=hashe(s);
            cnt[i]=hashe(s);
            if(appear[tmp]==1&&!vis[tmp])num++,vis[tmp]=1;
        }
        if(num==0){printf("0
    0
    ");return 0;}
        int st=0,en=0,sum=0,len=INF;
        while(1)
        {
            while(en<m&&sum<num)
            {
                if(mp[cnt[en]]==0&&appear[cnt[en]]==1)sum++;
                mp[cnt[en]]++;
                en++;
            }
            if(sum==num)len=min(len,en-st);
            if(sum<num)break;
            mp[cnt[st]]--;
            if(mp[cnt[st]]==0&&appear[cnt[st]]==1)sum--;
            st++;
        }
        printf("%d
    %d
    ",num,len);
        return 0;
    }
    View Code

    ...

  • 相关阅读:
    Oracle 数据库连接很慢,服务器监听一直等待
    Maven 根据不同的环境使用不同的配置
    Maven 根据不同的包路径打出不同的Jar包
    Linux 安装Nginx并支持SSL
    Nginx OpenSSL创建自签证书实现HTTP转HTTPS
    Oracle 服务突然中断处理(检查状态、重启)
    请求转发和重定向
    PHP PDO的简单封装(使用命名空间方式)
    PHP PDO学习小结
    MYSQL预处理机制
  • 原文地址:https://www.cnblogs.com/myrtle/p/11546323.html
Copyright © 2020-2023  润新知