[刷题之旅no34]字符串哈希

哈希表需要解决的问题:
1.确定函数
2.确定冲突解决办法
3.选择什么样的数据结构进行存储哈希表,开辟多大的空间
解决问题:
1.函数的确定:
如何根据一个字符串来吧函数确定出来呢?
字符串很长,每个字符都有确定的ascii码值,我需要做的就是确定一个计算公式,使得给一个字符串,我可以返回一个值
直接使用长度来确定感觉就很好。这样最多1500的长度,也有利于我进行操作。
故:H(x)=strlen(str)
2.冲突解决办法:
我认为可以直接使用链地址法则,
确定一个结构体,内部由一个字符串和一个next整数组成,数组大小直接开辟11500,这样不可能超出范围,cnt用来记录尾部,从1500之后开始,为前面的首字符串留下空间
步骤:
1.读取总字符串个数
2.循环,读取n个字符串
for
3.每读取一个字符串,字符串哈希计算其长度
4.找到数组对应下标
while(1)
flag0;填入,flag=1,cnt++,break;
flag
1,比较
相同,break
不同,判断next
next==0;直接填入当前tail的位置,flag=1;连上
next!=0;直接访问下一位
最后输出cnt即可
字符串比较用strcmp如果相等则返回0;
70分,其实还行,不算太失望,看看到底哪里出了问题把:
数据比对之后,发现我的错误都是在原来基础上多了1?
有意思!
这个错误可还行。
ok
发现错误。原来是将当前字符串填入尾端的时候
发生了
先填值,更新next=tail
tail++
再更新flag=1
顺序错了
应该先flag=1;
再tail++;
把能更新的都更新完再去把tail拨针移动到下一位
大佬的思路:
进制哈希
由于思路较长,所以我们单开一个博文进行书写
[算法学习No14]进制哈希BKDR Hash
bkdr hash代码:
时间复杂度要高一点,除了每次的计算量比较大之外,还有sort函数排序是个大工程(为了查重)

#include<stdio.h>
#include<string.h>
unsigned int arr[10050]={0},k=131,ans,n;
char s[1505];
unsigned int hash()
{
	ans=0;
	for(int i=1;i<=strlen(s);i++)
	{
		ans=ans*k+(unsigned int)s[i];
	}
	return ans;
}
void sort()
{
	unsigned int tmp;
	for(int gap=n/2;gap>0;gap=gap/2)
	{
		for(int i=gap+1;i<=n;i++)
		{
			for(int j=i;j-gap>0&&arr[j]<arr[j-gap];j=j-gap)
			{
				tmp=arr[j];
				arr[j]=arr[j-gap];
				arr[j-gap]=tmp;
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		arr[i]=hash();
	}
	sort();
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		if(arr[i]!=arr[i+1])
		{
			cnt++;
		}
	}
	printf("%d",cnt);
	return 0;
}

我自己的思路的代码:

#include<stdio.h>
#include<string.h>
typedef struct
{
	char str[1505];
	int next,flag;
}Str;
Str hash[13000];
int tail=1600,cnt=0,n,ind;
char input[1505];
void init()
{
	for(int i=1;i<=n;i++)
	{
		hash[i].flag=0;
		hash[i].next=0;
	}
}
void Hash()
{
	ind=strlen(input);
	while(1)
	{
		if(hash[ind].flag==0)
		{
			strcpy(hash[ind].str,input);
			cnt++;
			hash[ind].flag=1;
			break;
		}
		else
		{
			if(strcmp(hash[ind].str,input)==0)
			{
				break;
			}
			else//说明二者并不相等,继续往后遍历 
			{
				if(hash[ind].next==0)//下一位已经没有了,而且当前字符串也不匹配,直接填入了 
				{
					hash[ind].next=tail;
					strcpy(hash[tail].str,input);
					hash[tail].flag=1;
					tail++;
					cnt++;
					break;
				}
				else
				{
					ind=hash[ind].next;
				}	
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	init();
	for(int i=1;i<=n;i++)
	{
		scanf("%s",input);
		Hash();
	}
	printf("%d",cnt);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用字符串哈希算法来加速字符串的比较操作。 引用\[1\]中的代码示例展示了一个使用字符串哈希算法的C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。其中,哈希值的计算使用了前缀和数组和幂运算。 引用\[2\]中的解释指出,使用字符串哈希的目的是为了比较字符串时不直接比较字符串本身,而是比较它们对应映射的数字。这样可以将子串的哈希值的时间复杂度降低到O(1),从而节省时间。 引用\[3\]中的代码示例也展示了一个使用字符串哈希算法的C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。与引用\[1\]中的代码类似,哈希值的计算也使用了前缀和数组和幂运算。 综上所述,字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用前缀和数组和幂运算来计算字符串哈希值,并通过比较哈希值来判断两个子串是否相等。 #### 引用[.reference_title] - *1* [C++算法题 # 33 字符串哈希](https://blog.csdn.net/weixin_44536804/article/details/123425533)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [字符串哈希(c++)](https://blog.csdn.net/qq_41829492/article/details/120980055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [AcWing 841. 字符串哈希(C++算法)](https://blog.csdn.net/YSA__/article/details/108453403)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值