算法入门竞赛经典 哈希算法

算法字符串map以及hash表

1.字符串哈希:
如果让你匹配2个字符串是否相等
一种想法就是把长度每个字符值加在一起,判断是否相等
这样ab和ba就是相等;
所以我们这边引入hash表的算法
哈希算法就是把每个字符对应一个数值,每次加上该位的x的n次幂,类似2进制的算法;
比如
”123“我们把进制设为10的话
”123“对应的就是11010+2*10+3;
一个字符串hash的算法可以变为:

ull hash(string s)
{
    
    
	ull ans=1;
	for(int i=0;i<s.size();++i)
	{
    
    
		ans=(ans*x+(ull)s[i])%mod;
	}
	return ans;
}

模拟上诉过程,这里的x选择有技巧哦,实验发现像131
1331,13331,1333331这样的数乘上去,就少了哈希冲突具体可以看看其它人博客什么叫哈希冲突;

接下来如果数值很大的话,我们要取余数一般对2的64取余数,unsinged long long的最大值;

ull mod=212370440130137957ll;

接下来就是代码,2个数的哈希值不一样,数字就不一样;

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull x=13331;
ull mod=212370440130137957ll;
ull hash(string s)
{
    
    
	ull ans=1;
	for(int i=0;i<s.size();++i)
	{
    
    
		ans=(ans*x+(ull)s[i])%mod;
	}
	return ans;
}
ull a[10010];
int main()
{
    
    
	ull n;cin>>n;
	string s;
	int i=0;
	while(n)
	{
    
    
		cin>>s;
		a[i++]=hash(s);
		n--;
	}
	sort(a,a+i);
	int ans=0;
	for(int j=0;j<i;++j)
	{
    
    
		if(a[j]!=a[j+1])
	 	ans++;
	}
	cout<<ans;
	return 0;
}

	
	

2.map绑定2个类型结构体:
题目:洛谷密码
思路:
1.因为一个单词和数字相匹配,一路看过来我写的blog的人都知道这个是个小技巧,多个属性在一起的时候就用一个结构体把他们绑定在一起这里有2个stl的结构体;
map绑定2个随意类型,pair绑定2个int类型:
这里一个单词绑定一个数值

map<string,int>

2.每次输入一个值,就把对应得int存入数组;
3.sort排序;
代码:

/*
1.输入字符串
2.每个字符串如果在map里面就在用一个int数组里面存入这个值
3.sort,然后输出; 



*/
#include <iostream>
#include <map> 
#include <algorithm>
using namespace std;
int y[10010],top=0;
int main()
{
    
    
	map<string,int>q;
	  q["one"]=1;q["two"]=2;q["three"]=3;q["four"]=4;q["five"]=5;q["six"]=6;q["seven"]=7;q["eight"]=8;q["nine"]=9;q["ten"]=10;
     q["eleven"]=11;q["twelve"]=12;q["thirteen"]=13;q["fourteen"]=14;q["fifteen"]=15;q["sixteen"]=16;q["seventeen"]=17;q["eighteen"]=18;q["nineteen"]=19;q["twenty"]=20;
     q["a"]=1;q["both"]=2;q["another"]=1;q["first"]=1;q["second"]=2;q["third"]=3;
	string s;
	for(int i=0;i<6;++i)
	{
    
    
		cin>>s;
		if(q[s]!=0)
		{
    
    
			int k=q[s]*q[s]%100;
			if(k==0)continue;
			y[++top]=k;
		}
	}
 
	 sort(y,y+top);
	 cout<<y[0];
	 for(int i=1;i<=top;i++){
    
    
	 	if(y[i]<10)cout<<0;
	 	cout<<y[i];
	 }
	 return 0;
	 
} 

这里只要输入一个字符串,存在,就把对应的数字存入,然后排序;
3.sscanf以及sprintf妙用
题目:口算练习题
思路:
1*.利用一个string 存入第一个输入的值*,这里注意不要用
char,为什么呢?因为第一个如果是数字的话,char存下来就不能把这个数字转化成int的整数了;
2.sprintf将数组输入到字符串
eg.
sprintf(数组名称,”%d+%d=%d,a,b,a+b);
这里数组存入的就是[%d,+,%d,=,%d];%d会被占位掉;
3.sscanf输入变化
eg sscanf(s,"%d",&a);
把s以%d存入到整数a里面去;

/*
1.输入一个字符串;
2,如果是a b c输入2个整数输出;
3.不是的话,就把第一个数转化为int,查看上一次的char是什么; 


*/
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
using namespace std;
char m[100010];
char s[10010];
int main()
{
    
    
	char t;
	int n,a,b;cin>>n;
	while(n)
	{
    
    
		cin>>s;
		memset(m,0,sizeof(m));
		if(s[0]=='a')
		{
    
    
			
			cin>>a>>b;
			cout<<a<<"+"<<b<<"="<<a+b<<endl;
			sprintf(m,"%d+%d=%d",a,b,a+b);
			cout<<strlen(m)<<endl;
			t='+';
		}
		else if(s[0]=='b')
		{
    
    
			cin>>a>>b;
			cout<<a<<"-"<<b<<"="<<a-b<<endl;
			sprintf(m,"%d-%d=%d",a,b,a-b);
			cout<<strlen(m)<<endl;
			t='-';
		}
		else if(s[0]=='c')
		{
    
    
			cin>>a>>b;
			cout<<a<<"*"<<b<<"="<<a*b<<endl;
			sprintf(m,"%d*%d=%d",a,b,a*b);
			cout<<strlen(m)<<endl;
			t='*';
		}
		else
		{
    
    
			sscanf(s,"%d",&a);
			cin>>b;
			if(t=='+')
			{
    
    
				cout<<a<<"+"<<b<<"="<<a+b<<endl;
				sprintf(m,"%d+%d=%d",a,b,a+b);
				cout<<strlen(m)<<endl;
			}
			else if(t=='-')
			{
    
    
				cout<<a<<"-"<<b<<"="<<a-b<<endl;
				sprintf(m,"%d-%d=%d",a,b,a-b);
				cout<<strlen(m)<<endl;
			}
			else if(t=='*')
			{
    
    
				cout<<a<<"*"<<b<<"="<<a*b<<endl;
				sprintf(m,"%d*%d=%d",a,b,a*b);
				cout<<strlen(m)<<endl;
			}
		}
		n--;
	}
 } 

只要注意string不能符合到sscanf这个里面去:用char s[]
cin>>s;
好了 字符串博大精深,大家加油,午安,打工人。
周末有空的话再更新一下kmp算法hash的应用;

猜你喜欢

转载自blog.csdn.net/m0_51373056/article/details/109358293