POJ1200-hash基础

来源:互联网 发布:网络运营许可证 编辑:程序博客网 时间:2024/05/16 09:44

题意大致是:给你一个字符串,里面有nc个字符,问长度为n的子串有多少种可能

思路:给每个不同的字母赋值,0到nc-1,然后做一个nc进制的hash,思路很简单但是由于是第一次写hash很所细节问题没有考虑

比如,编号数组不能从0开始编号,还有不能再遍历长字符串使用时用i<strlen(s)操作,特别费时间,超时好多回。

代码如下:

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;int vis[300];bool Hash[16000000];char s[16000000];int main(){    int n,nc;    while(scanf("%d%d",&n,&nc)!=EOF) {        scanf("%s",s);        memset(vis,0,sizeof vis);        memset(Hash,0,sizeof Hash);        int nn=1;        int len=strlen(s);    //这步很关键如果将strlen(s)直接放在循环内,会有一个比较大的时间常数        for(int i=0;i<len;i++) {            if(vis[s[i]]==0) {      //注意这里不能从0开始标号,一定要从1开始编号                vis[s[i]]=nn++;            }            if(nn==nc+1) break;        }        int ans=0;        int x=0;        for(int i=0;i<n;i++) {            x=x*nc+vis[s[i]]-1;        }       // cout << x << endl;        Hash[x]=1;        ans++;        int mod=1;        for(int i=1;i<n;i++)            mod*=nc;      //  cout << "mod" << mod << endl;        for(int i=1;i+n<=len;i++) {          //  x=(x%mod)*nc+vis[s[i+n-1]]-1;  //取余操作比较费时间            x=(x-(vis[s[i-1]]-1)*mod)*nc+vis[s[i+n-1]]-1;            if(Hash[x]==0) {            //    cout << i << " " <<x <<endl;                ans++;                Hash[x]=1;            }        }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击