您的位置:首页 > 其它

POJ 1200 Crazy Search 解题报告

2009-03-30 14:57 253 查看
#include<stdlib.h>
#include<memory.h>
#include<stdio.h>
#include<iostream>
using namespace std;
#define MAX 5000000
#define P	3313
//用静态链表代替动态链表
struct Hash{
int hash;
int next;
};
Hash h[MAX];
int c[MAX];
char x[MAX];
int main()
{
int n,nc;
while(scanf("%d%d",&n,&nc)!=EOF)
{
memset(c,0,sizeof(c));
memset(h,0,sizeof(h));
//tmp1用于储存字符串转换为26进制的数
//tmp2用于储存哈希值
int tmp1,tmp2,zz,ptr = 1,res = 0;
cin >> x;
bool flag;
int len = strlen(x) - n + 1;
for(int i = 0; i < len; i++)	{
flag = true;
tmp1 = 0;
tmp2 = 0;
for(int j = 0; j < n; j++){
tmp1 = tmp1*26 + x[i+j]-'a';
tmp2 = tmp2*P + x[i+j]-'a';
}
tmp1 = abs(tmp1)%MAX;
tmp2 = abs(tmp2)%MAX;
zz = c[tmp1];
while(zz)
if(h[zz].hash == tmp2){
flag = false;
break;
}
else
zz = h[zz].next;
if(flag){
res++;
h[ptr].hash = tmp2;
h[ptr].next = c[tmp1];
c[tmp1] = ptr++;
}
}
printf("%d/n",res);
}
return 0;
}
//Accepted 59840K 422MS G++ 1014B


这段代码的效率比较低,如果换作scanf可以在200ms内ac,想法比较直观,但没充分利用题目所给的nc

下面是参考了某牛的代码后做的

#include<stdlib.h>
//这题将字符串转换为一个nc进制的数,判断这个
//数是否重复出现即可
#include<memory.h>
#include<stdio.h>
#include<iostream>
using namespace std;
#define MAX 20000000
bool c[MAX];
char x[MAX];
//将字母转换为对应的数字,因为字母可能不是连续的
//如nc = 3时可能会有aeccc这种字符串
//处理后a,c,e分别代表0,1,2
int ascii[256];
int main()
{
int n,nc;
while(scanf("%d%d/n",&n,&nc)!=EOF)
{
memset(c,0,sizeof(c));
memset(ascii,0,sizeof(ascii));
int tmp,res(0);
scanf("%s",x);
int len = strlen(x);
//将出现过的字母都标记为-1(true)
for(int i = 0; i < len; i++)
ascii[x[i]] = -1;
int zz = 0;
//为出现过的字母分配数字
for(int i = 0; i < 256; i++)
if(ascii[i])
ascii[i] = zz++;
bool flag;
len = len - n + 1;
for(int i = 0; i < len; i++)	{
flag = true;
tmp = 0;
//将子字符串转换为nc进制数
for(int j = 0; j < n; j++)
tmp = tmp*nc + ascii[x[i+j]];
tmp = abs(tmp)%MAX;
if(!c[tmp]){
res++;
c[tmp] = true;
}
}
printf("%d/n",res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: