poj 1200 || zoj 1507 Crazy Search (Hash表)

来源:互联网 发布:大富豪3.29源码 编辑:程序博客网 时间:2024/05/16 05:27

题目链接:   http://poj.org/problem?id=1200

题目大意:  给出两个数字N和NC,一行字符串

                    这行字符串最多出现NC个字符

                    寻找长度为N的不同子串个数

解题思路:   字符串的长度最长为1600万,用strcmp()函数判断次数太多,肯定会TLE

                    开始用了BKDRHask,和ELFHask都WA,说明有些字串的hash值相等

                    为了避免这种情况我用链表来处理冲突,但是爆内存了,原因是数组太大!

                    最后把问题转化成NC进制,AC了

                    这道题可以用一个很巧妙的方法,将数值降到最小:

           如:

                    3 3

                    abcabc

                    abc:1x3^2+2x3^1+3x3^0=18

                    bca:2x3^2+3x3^1+1x3^0=28

                    cab:3x3^2+1x3^1+2x3^0=32

                    abc:1x3^2+2x3^1+3x3^0=18

                    3

代码:

//hash基础题, 转化为 nc进制#include <stdio.h>#include <string.h>#define MAX 1600000char ch[MAX];int Hash[MAX*10]={0},a[256]={0};int main(){    int i,j,h,t,n,nc,num;    scanf("%d%d%s",&n,&nc,ch);    memset(a,-1,sizeof(a));    for(i=0;ch[i]!='\0';i++)    {        if(a[ch[i]]==-1)        {            a[ch[i]]=1;        }    }    for(i=0,num=0;i<256;i++)    {        if(a[i]!=-1)            a[i]=num++;     //***减少数的大小,防止数组不够大,从0开始!    }    for(i=0,t=0;ch[i+n-1]!='\0';i++)    {        h=0;        for(j=i;j<i+n;j++)        {            h=h*nc+a[ch[j]];        }        if(!Hash[h])  //判断之前是否存在        {            Hash[h]=1;            t++;    //新加入的标记        }    }    printf("%d\n",t);    return 0;}

注:原创文章,转载请注明出处