Poj 1200 Crazy Search(字符串Hash)

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;
}

 

转载于:https://www.cnblogs.com/Mrleon/p/8424434.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值