• HDOJ--4821--String【弦hash】


    联系:http://acm.hdu.edu.cn/showproblem.php?pid=4821

    题意:给一个字符串,选m个长度为l的子串组成新的串。要求这m个子串互不同样,问有多少种组合。


    字符串hash题目,曾经没做过,做这道之前还用bkdrhash做了两道简单的题目。POJ1200和HDU1800。

    用base数组记录乘了几个seed,base[i]表示seed^i,这个数组在之后计算子串hash值的时候会用到,先预处理一遍节省时间。

    假设字符串从前往后hash。则hash[ i ] - hash[ i - l ] * base[ l ] 就是子串 [ i - l , i ] 的hash值,而从后往前hash的话 hash[ i ] - hash[ i + l ] * base[ l ] 就是子串 [ i , i + l ] 的hash值。

    推导过程:以从前往后hash为例。如果字符串abab,子串长度2。则

    i = 4时的hash值( ( ( (0+a)*seed+b ) * seed +a ) * seed + b ) ,

    i - l = 2的hash值( (0+a)*seed+b )。乘base[2]之后 ( ( ( (0+a)*seed+b ) * seed  ) * seed  )

    二者相减为a * seed + b。就是区间 [ i - l, i ] 相应字母 ab 的hash值。

    之后依照每一点枚举m个l长度的子串,当他们hash值不同一时候就是一个结果。


    #include<cstring>
    #include<string>
    #include<fstream>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<ctime>
    #include<cstdlib>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define PI acos(-1.0)
    #define MAXN 100010
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define seed 131
    typedef long long ll;
    typedef unsigned long long ull;
    
    
    char s[MAXN];
    ull base[MAXN],Hash[MAXN];
    map<ull,int> mp;
    int main(){
        int m,l,i,len,ans;
        base[0] = 1;
        for(i=1;i<MAXN;i++) base[i] = base[i-1] * seed;
        while(scanf("%d%d",&m,&l)!=EOF){
            scanf("%s",s);
            ans = 0;
            len = strlen(s);
            Hash[len] = 0;
            for(i=len-1;i>=0;i--){
                Hash[i] = Hash[i+1] * seed + s[i] - 'a';
            }
            for(i=0;i<l&&i+m*l<len;i++){
                mp.clear();
                for(int j=i;j<i+m*l;j+=l){
                    ull temp = Hash[j] - Hash[j+l] * base[l];
                    mp[temp]++;
                }
                if(mp.size()==m)    ans++;
                for(int j=i+m*l;j+l<=len;j+=l){
                    ull temp = Hash[j-m*l] - Hash[j-(m-1)*l] * base[l];
                    mp[temp]--;
                    if(!mp[temp])   mp.erase(temp);
                    temp = Hash[j] - Hash[j+l] * base[l];
                    mp[temp]++;
                    if(mp.size()==m)    ans++;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    繁体解决方案一,ASP,JSP,PHP,DotNet任何开发通用
    18.观察者模式(Observer Pattern)
    存储过程小技巧(2)从动态查询SQL中返回值给变量
    DotNet学习
    询问:有没有用C#写的C/S模式下的网页编辑工具
    dotNet繁体解决方案
    svn感叹号大全
    svn中出现红色感叹号
    Varnish配置,Error 503解决之道
    varnish清除缓存的方法
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4854497.html
Copyright © 2020-2023  润新知