HUEL2022hash题代码

 A题 UVA - 10282

题意:输入是本国单词和对应的外国单词词典,然后给你几个外国单词,输出对应的本国单词,没有的话输出“eh”。

注意:在第一个输入本国语言与对应的外国语言的时候一个空行代表输入结束

思路:用map进行映射就可以了

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<map>
#include<sstream>
using namespace std;
map<string,string> mp;

int main()
{
	string s;
	while(getline(cin,s),s!="")
	{
		string s1,s2;
		stringstream ss;//输入输出流,碰到空格停止
		ss<<s;
		ss>>s1;ss>>s2;
		mp[s2]=s1;
	}
	while(cin>>s)
	{
		if(!mp.count(s)) puts("eh");
		else cout<<mp[s]<<endl;
	}
	return 0;
}

B题 POJ - 1200

题意:在一个字符串中求有多少个长度为n的不同的子字符串,字符串最多有NC个不同的字母。

思路:hash思想,但没有那么麻烦,先统计不同的字母的个数m,然后遍历每一个长度为n的子字符串,将其变成m进制的数,统计该数是否出现过

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=16000010;
int mp[30];
char c[N];
bool st[N];
int n,m,cnt,ans;

int main()
{
	cin>>n>>m;
	scanf("%s",c+1);
	int len=strlen(c+1);
	for(int i=1;i<=len;i++)
	{
		if(!mp[c[i]-'a']) mp[c[i]-'a']=++cnt;//统计不同字母的个数,并将每一个字母映射成m中的一个数
	}
	for(int i=n;i<=len;i++)
	{
		int res=0;
		for(int j=i-n+1;j<=i;j++)
			res=res*cnt+mp[c[j]-'a'];//将长度为n的子字符串映射成m进制
		if(!st[res])//如果这个子字符串未出现过就答案加一
		{
			ans++;
			st[res]=true;
		}
	}
	cout<<ans<<endl;
	return 0;
}

C题 SPOJ - EPALIN

题意:将一个字符串变为回文串

思路:将字符串遍历,求从第i位到字符串最后是一位(第n位)回文串的i的最小值,然后现将字符串输出,再将字符串第i-1位到第一位输出

求第i位到第n位是回文串的时候可以用两个hash数组hl,hr。hl表示字符串正顺序的hash值,hr代表字符串反顺序的hash值。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100010,P=131;
typedef unsigned long long ULL;
ULL p[N],hl[N],hr[N];
char c[N];
int n,idx;

void init()
{
	n=strlen(c+1);
	p[0]=1;
	for(int i=1;i<=n;i++)
	{
		p[i]=p[i-1]*P;
		hl[i]=hl[i-1]*P+c[i];
		hr[i]=hr[i-1]*P+c[n-i+1];
	}
}

ULL get(ULL h[],int l,int r)
{
	return h[r]-h[l-1]*p[r-l+1];
}

int main()
{
	while(~scanf("%s",c+1))
	{
		init();
		for(int i=1;i<=n;i++)
		{
			if(get(hl,i,n)==get(hr,1,n-i+1)) //倒序的第1位对应着正序的第n位,第二位对应着第                n-1位
			{
				idx=i;
				break;
			}
		}
		printf("%s",c+1);
		for(int i=idx-1;i;i--) printf("%c",c[i]);
		puts("");
	}
	
	return 0;
}

D题 SCU - 4438

题意:从待匹配串中删去模式串成为一个新串,再从新串中删去模式串,以此类推,直至删完,然后输出最后剩余删完模式串的待匹配串。

思路:将待匹配串中的字符一个一个存入一个数组(类似栈)中,用一个指针top指向栈顶,若数组长度大于等于模式串长度n,判断一下数组中的后n个字符正顺序组成的字符串的hash值是否与模式串hash值相等,相等的话top-n

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ULL;
const int N=5000010,P=131;
ULL h[N],p[N];
char s1[N],s2[N],ans[N];
int n,m,top;

ULL get(int l,int r)
{
	return h[r]-h[l-1]*p[r-l+1];
}

void solve()
{
	top=0;
	p[0]=1;
	n=strlen(s1+1);
	ULL x=0;//x表示模式串hash值
	for(int i=1;i<=n;i++)
		x=x*P+s1[i];
	m=strlen(s2+1);
	for(int i=1;i<=m;i++)
	{
		ans[++top]=s2[i];
		h[top]=h[top-1]*P+ans[top];
		p[top]=p[top-1]*P;
		if(top>=n)
		{
			if(get(top-n+1,top)==x)
			{
				top-=n;
			}
		}
	}
	for(int i=1;i<=top;i++)
		printf("%c",ans[i]);
	puts("");
}

int main()
{
	while(~scanf("%s%s",s1+1,s2+1)){
		solve();
	}
}

E题 POJ - 3974

题意:求字符串中的最大回文串

思路:在每个字符两边加上一个特殊字符,使回文串的长度变为奇数,二分长度,遍历字符串判断二分的长度是否有回文串,如果有往后二分,没有往前二分

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ULL;
const int N=2000010,P=131;
char c[N];
ULL h1[N],h2[N],p[N];
int n,t;

void init()
{
	p[0]=1;
	n=strlen(c+1);
	n=2*n+1;
	c[n]='#';
	for(int i=n-1;i;i-=2)
	{
		c[i]=c[i/2];
		c[i-1]='#';
	}
	for(int i=1;i<=n;i++)
	{
		p[i]=p[i-1]*P;
		h1[i]=h1[i-1]*P+c[i];
		h2[i]=h2[i-1]*P+c[n-i+1];
	}
}

ULL get(ULL h[],int l,int r)
{
	return h[r]-h[l-1]*p[r-l+1];
}

bool check(int mid)
{
	for(int i=mid;i+mid<=n;i++)
	{
		int l=i-mid,r=i+mid;
		if(get(h1,l,r)==get(h2,n-r+1,n-l+1)) return true;
	}
	return false;
}

int main()
{
	while(scanf("%s",c+1))
	{
		if(!strcmp(c+1,"END")) break;
		init();
		int l=1,r=n;
		while(l<r)
		{
			int mid=l+r+1>>1;
			if(check(mid)) l=mid;
			else r=mid-1;
		}
		printf("Case %d: %d\n",++t,l);
	}
	return 0;
}

F题 POJ - 2774

题意:求两个字符串S,P中的最长的相同子串

思路:二分子串长度mid,将长度为mid的S中的子串hash值存到vector中(不能用map,会被卡),然后将vector排序,遍历P串,判断P串中长度为mid的子串hash值是否在vector中(可以用vector的binary_search函数),存在就往后二分长度,不存在就往前二分长度

时间复杂度:O(nlognlogn)

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
typedef unsigned long long ULL;
const int N=100010,P=131;
ULL h1[N],h2[N],p[N];
char s1[N],s2[N];
int n,m;

void init()
{
	n=strlen(s1+1);m=strlen(s2+1);
	p[0]=1;
	for(int i=1;i<=n;i++)
	{
		p[i]=p[i-1]*P;
		h1[i]=h1[i-1]*P+s1[i];
	}
	for(int i=1;i<=m;i++)
		h2[i]=h2[i-1]*P+s2[i];
}

ULL get(ULL h[],int l,int r)
{
	return h[r]-h[l-1]*p[r-l+1];
}

bool check(int mid)
{
	vector<ULL>v;
	for(int i=mid;i<=n;i++)
	{
		int l=i-mid+1,r=i;
		v.push_back(get(h1,l,r));
	}
	sort(v.begin(),v.end());
	for(int i=mid;i<=m;i++)
	{
		int l=i-mid+1,r=i;
		ULL x=get(h2,l,r);
		if(binary_search(v.begin(),v.end(),x))
			return true;
	}
	return false;
}

int main()
{
	scanf("%s%s",s1+1,s2+1);
	init();
	int l=0,r=min(n,m);
	while(l<r)
	{
		int mid=l+r+1>>1;
		if(check(mid)) l=mid;
		else r=mid-1;
	}
	printf("%d\n",l);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值