题目链接: 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 1600000
char 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;
}
注:原创文章,转载请注明出处