1 /*****************************************************
2 哈希应用
3 将字符串转换成nc进制的数,判断这个数是否重复出现即可
4 其中要将字母转化成对应的数字,因为字母可能不是连续的
5 (这点一定要注意,所以不能单纯的用char[i]-'a'来转化)
6 如nc = 3时可能 会有aeccc这种字符串
7 处理后要将a,c,e,分别代表0,1,2
8 ******************************************************/
9
10 #include<iostream>
11 #include<cmath>
12 #include<cstring>
13 usingnamespace std;
14 #define MAX 20000000
15 bool c[MAX];
16 char x[MAX];
17 int ascii[256];
18 /*****************************************************/
19 int main(){
20 int n,nc;
21 while(scanf("%d%d\n",&n,&nc)!=EOF){//丢了EOF会报超时
22 //用scanf要注意
23 memset(c,0,sizeof(c));
24 memset(ascii,0,sizeof(ascii));
25 int temp,res=0;//res用来计数
26 scanf("%s",x);
27 int len=strlen(x);//返回字符串\0之前的个数
28 //cout<<len<<endl;
29 //将出现过得字母都标记为-1;
30 for(int i=0;i<len;i++){
31 ascii[x[i]]=-1;
32 }
33 int zz=0;
34 //为出现的过得数字分配数字
35 for(int i=0;i<256;i++){
36 if(ascii[i])ascii[i]=zz++;
37 }
38 bool flag;
39 len = len-n+1;
40 for(int i=0;i<len;i++){
41 flag=true;
42 temp=0;
43 //将字符串转换成nc进制的数字
44 for(int j=0;j<n;j++)
45 temp=temp*nc+ascii[x[i+j]];
46 //此处有一疑问:万一有两个超过MAX的
47 //取模后正好相同怎么区分哦...(可能出现吗)
48 temp = abs(temp)%MAX;//溢出则为负数
49 if(!c[temp]){
50 res++;
51 c[temp]=true;
52 }
53 }
54 printf("%d\n",res);
55 }
56 return0;
57 }
58
http://poj.org/problem?id=1200