题目描述:
Epicure先生正在编撰一本美食百科全书。为此,他已从众多的同好者那里搜集到了一份冗长的美食提名清单。既然源自多人之手,其中自然不乏重复的提名,故必须予以筛除。Epicure先生因此登门求助,并认定此事对你而言不过是“一碟小菜”,相信你不会错过在美食界扬名立万的这一良机。
输入格式:
第1行为1个整数n,表示提名清单的长度。以下n行各为一项提名。
要求:
1 < n < 6 * 10^5
提名均由小写字母组成,不含其它字符,且每项长度不超过40字符。
输出格式:
所有出现重复的提名(多次重复的仅输出一次),且以其在原清单中首次出现重复(即第二次出现)的位置为序。
输入样例:
10
brioche
camembert
cappelletti
savarin
cheddar
cappelletti
tortellni
croissant
brioche
mapotoufu
输出样例:
cappelletti
brioche
题解:
//本题的逻辑结构:散列表
//本题的存储结构:链式
//解题思路和算法:通过散列函数做位移映射,将数据存入散列表,关键词与地址一一对应,同一个
// 关键词只在散列表中出现一次,如果出现多次则插入失败,若插入失败则插入另一个散列表,
// 由此可输出重复的关键词,且保证输出重复的关键词只输出一次
//效率:时间复杂度O(n)、空间复杂度O(n):
//测试数据: (1)输入:10
// brioche
// camembert
// cappelletti
// savarin
// cheddar
// cappelletti
// tortellni
// croissant
// brioche
// mapotoufu
// 输出:cappelletti
// brioche
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<math.h>
#define true 1
#define false 0
#define MAXTABLESIZE 100000
typedef int bool;
typedef char * ElementType;
typedef int Index;
typedef Index Position;
typedef enum {Legitimate, Empty, Deleted} EntryType;
typedef struct HashEntry Cell;
struct HashEntry{
ElementType Data;
EntryType Info;
};
typedef struct TblNode * HashTable;
struct TblNode{
int TableSize;
Cell * Cells;
};
int NextPrime(int N){
int i, p=(N%2)?N+2:N+1;
while(p<=MAXTABLESIZE){
for(i = (int)sqrt(p); i>2; i--)
if(!(p%i))break;
if(i==2)break;
else p+=2;
}
return p;
}
HashTable CreateTable(int TableSize){
HashTable H;
int i;
H = (HashTable)malloc(sizeof(struct TblNode));
H->TableSize = NextPrime(TableSize);
H->Cells = (Cell *)malloc(H->TableSize*sizeof(Cell));
for(int i=0;i<H->TableSize;i++){
H->Cells[i].Info = Empty;
}
return H;
}
int Hash(const char *Key, int TableSize){
unsigned int H = 0;
while(*Key !='\0')
H = (H<<5)+*Key++;
return H%TableSize;
}
Position Find(HashTable H, ElementType Key){
Position CurrentPos, NewPos;
int CNum = 0;
NewPos = CurrentPos = Hash(Key, H->TableSize);
while(H->Cells[NewPos].Info!=Empty && H->Cells[NewPos].Data!=Key){
if(++CNum%2){
NewPos = CurrentPos+(CNum+1)*(CNum+1)/4;
if(NewPos>=H->TableSize)
NewPos = NewPos %H->TableSize;
}
else{
NewPos = CurrentPos - CNum *CNum/4;
while(NewPos<0){
NewPos += H->TableSize;
}
}
}
return NewPos;
}
bool Insert(HashTable H, ElementType Key){
Position Pos = Find(H, Key);
if(H->Cells[Pos].Info!=Legitimate){
H->Cells[Pos].Info = Legitimate;
H->Cells[Pos].Data = Key;
return true;
}
else{
return false;
}
}
int main(){
char arr[1000][1000];
HashTable table1 = CreateTable(MAXTABLESIZE);
HashTable table2 = CreateTable(MAXTABLESIZE);
int n;
int count =0;
scanf("%d", &n);
for(int i = 0;i<n;i++){
char string1[MAXTABLESIZE];
scanf("%s", string1);
if(Insert(table1, string1))
continue;
else{
if(Insert(table2, string1)){
for(int j = 0;j<strlen(string1);j++){
arr[count][j] = string1[j];
}
count++;
}
else{
continue;
}
}
}
for(int i = 0;i<count;i++){
for(int j = 0;j<strlen(arr[i]);j++){
printf("%c", arr[i][j]);
}
printf("\n");
}
return 0;
}