码迷,mamicode.com
首页 > 其他好文 > 详细

Poj 1200 Crazy Search(字符串Hash)

时间:2018-02-07 00:34:11      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:mes   scan   ret   turn   一个   长度   复杂度   blank   时间复杂度   

Poj 1200

题意:给你一个n和m以及一个有m个不同字母组成的字符串,问有多少个长度为n的不同字符子串;

题解:以m为进制进行Hash。虽然是看了解题报告才会的但必须要理解并且学会运用:https://www.cnblogs.com/gj-Acit/archive/2013/05/15/3080734.html

#include<cstring>//别用set,set的添加是红黑树实现时间复杂度是O(logN),在这里会超时
#include<cstdio>
#define ull unsigned long long
using namespace std;
const int N=1e7+6e6+5;
using namespace std;
int p[N];
int len;
char str[N];
bool hash_[N];
int main(){
    int n,m;
    scanf("%d %d %s",&n,&m,str+1);
    len=strlen(str+1);
    int j=0;
    for(int i=1;i<=len;i++){
        if(!p[str[i]])p[str[i]]=++j;//以m为进制数,将各个字母分别用数字表示进行hash
        if(j==m)break;
    }
    ull Base=1;
    ull Hash=0;
    for(int i=1;i<=n;i++){//首先将前n个数将m进制转换为10进制
        Hash=Hash*m+p[str[i]]-1;//减一是为了因为m进制数为0到m-1
        Base*=m;
    }
    Base/=m;
    hash_[Hash]=1;
    int ans=1;
    for(int i=2;i+n<=len+1;i++){
        Hash=(Hash-(p[str[i-1]]-1)*Base)*m+p[str[i+n-1]]-1;//原Hash减去子串首字母代表的数乘以Base得到的是剩下字母所生成的10进制数那么再乘以一个m在加上新进的一个字母所代表的数,得到的是新子串所代表的10进制数(即其hash值)
        if(!hash_[Hash]){
            hash_[Hash]=1;
            ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

Poj 1200 Crazy Search(字符串Hash)

标签:mes   scan   ret   turn   一个   长度   复杂度   blank   时间复杂度   

原文地址:https://www.cnblogs.com/Mrleon/p/8424434.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!