洛谷 P2580 于是他错误的点名开始了

题目背景

XS中学化学竞赛组教练是一个酷爱炉石的人。

他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次,然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉(详情请见已结束比赛 CON900)。

题目描述

这之后校长任命你为特派探员,每天记录他的点名。校长会提供化学竞赛学生的人数和名单,而你需要告诉校长他有没有点错名。(为什么不直接不让他玩炉石。)

输入格式

第一行一个整数 nn,表示班上人数。

接下来 nn 行,每行一个字符串表示其名字(互不相同,且只含小写字母,长度不超过 5050)。

第 n+2n+2 行一个整数 mm,表示教练报的名字个数。

接下来 mm 行,每行一个字符串表示教练报的名字(只含小写字母,且长度不超过 5050)。

输出格式

对于每个教练报的名字,输出一行。

如果该名字正确且是第一次出现,输出 OK,如果该名字错误,输出 WRONG,如果该名字正确但不是第一次出现,输出 REPEAT

输入输出样例

输入 #1复制

5  
a
b
c
ad
acd
3
a
a
e

输出 #1复制

OK
REPEAT
WRONG

说明/提示

  • 对于 40\%40% 的数据,n\le 1000n≤1000,m\le 2000m≤2000。
  • 对于 70\%70% 的数据,n\le 10^4n≤104,m\le 2\times 10^4m≤2×104。
  • 对于 100\%100% 的数据,n\le 10^4n≤104,m≤10^5m≤105。

用哈希算法做的,插入和搜索了两次,第二次嵌套在第一次内。

不说废话,直接上AC代码(总是只出现WRONG和REPEAT,反复改了好久,才发现只是insert函数的位置放错了,浪费了好多时间。。总觉得代码太长了,重复过多,明天再优化一下):

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;


/*--------------------------------------------------------------------------------------------------------------*/

typedef struct Node
{
	char *str;
	struct Node *next;
}Node;

typedef struct HashTable
{
	Node **data;//链表头地址的数组 
	int size;//哈希表的大小 
}HashTable;

Node *init_node(char *str,Node *head)//头插法 
{
	Node *p = (Node *)malloc(sizeof(Node));//先声明一个局部变量p 
	p->str = strdup(str);//strdup申请一片新的存储空间,并将str的内容拷贝到新的存储空间中,返回的是新的存储空间的地址 
	p->next = head;
	return p;
}
 
HashTable *init_hashtable(int n)
{
	HashTable *h = (HashTable *)malloc(sizeof(HashTable));
	h->size = n << 1;
	h->data = (Node **)calloc(sizeof(Node *),h->size);
	return h;
}

int BKDRhash(char *str)
{
	int seed = 31 , hash = 0;
	for(int i=0;str[i];i++) hash=hash*seed+str[i];
	return hash & 0x7fffffff;//为了保证返回的是个正值 
}

int insert(HashTable *h,char *str)//插入 
{
	int hash = BKDRhash(str);
	int ind = hash % h->size;
	h->data[ind] = init_node(str,h->data[ind]);
	return 1;
}//拉链法

int search(HashTable *h,char *str)//查找 
{
	int hash = BKDRhash(str);
	int ind = hash % h->size;
	Node *p = h->data[ind];
	while(p && strcmp(p->str,str)) p = p->next;
	return p!=NULL;
}

/*-------------------------------------------------------------------------------------------------------*/

typedef struct node
{
	char *str;
	struct node *next;
}node;

typedef struct hashtable
{
	node **data;//链表头地址的数组 
	int size;//哈希表的大小 
}hashtable;

node *init_node2(char *str,node *head)//头插法 
{
	node *q = (node *)malloc(sizeof(node));//先声明一个局部变量p 
	q->str = strdup(str);//strdup申请一片新的存储空间,并将str的内容拷贝到新的存储空间中,返回的是新的存储空间的地址 
	q->next = head;
	return q;
}
 
hashtable *init_hashtable2(int n)
{
	hashtable *h2 = (hashtable *)malloc(sizeof(hashtable));
	h2->size = n << 1;
	h2->data = (node **)calloc(sizeof(node *),h2->size);
	return h2;
}

int BKDRhash2(char *str)
{
	int seed = 31 , hash = 0;
	for(int i=0;str[i];i++) hash=hash*seed+str[i];
	return hash & 0x7fffffff;//为了保证返回的是个正值 
}

int insert2(hashtable *h2,char *str)//插入 
{
	int hash = BKDRhash2(str);
	int ind = hash % h2->size;
	h2->data[ind] = init_node2(str,h2->data[ind]);
	return 1;
}//拉链法

int search2(hashtable *h2,char *str)//查找 
{
	int hash = BKDRhash2(str);
	int ind = hash % h2->size;
	node *q = h2->data[ind];
	while(q && strcmp(q->str,str)) q = q->next;
	return q!=NULL;
}

/*-------------------------------------------------------------------------------------------------------*/
char s1[10010][55],s2[100010][55];
int main()
{
	HashTable *h = init_hashtable(10010);
	hashtable *h2 = init_hashtable2(10010);
	
	int n;//班上人数 
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>s1[i];
		insert(h,s1[i]);
	}
	
	int m;//教练报的名字个数 
	cin>>m;
	for(int i=0;i<m;i++)
	{
		cin>>s2[i];
		int k=search(h,s2[i]);
		if(k==0)
			cout<<"WRONG"<<endl;
		else
		{
			int k=search2(h2,s2[i]);
			insert2(h2,s2[i]);
			if(k==1)
				cout<<"REPEAT"<<endl;
			else
				cout<<"OK"<<endl;
		}
	}
	
}

RE是由于第二个数组开小了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值