HDU4821 (2020.3.12训练E题)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4821在这里插入图片描述
题意:给出M和L的值,字符串s,求其中满足条件的M*L长度子串个数(条件:可分为M个长度为L各不相同的子串)

我们使用哈希函数,有一个长为M*L的窗口滑动,对每个遇到的L的子串求哈希值,比较是否就放入map中判断是否有重复,前M个判断好了,下一步就将第M+1个放入map,前第M个提出,每次满足条件就++,最后输出结果

这位博主的题解写的挺好的,顺便发一下:https://www.cnblogs.com/tigerisland/p/7564689.html

ac代码如下:

#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100100
typedef unsigned long long  int ull;
typedef long long ll;
char str[maxn];
ll xp[maxn];
ll hash1[maxn];
ll base = 175;
map<ll, int>mp;
void init()
{
	xp[0] = 1;
	for (int i = 1; i < maxn; i++)
		xp[i] = xp[i - 1] * base;
}
ll get_hash(int i, int L)
{
	return hash1[i + L - 1] - hash1[i - 1] * xp[L];
}
 
int main()
{
	int M, L;
	init();
	while (scanf("%d%d",&M,&L)!=EOF)
	{
		scanf("%s", str + 1);
		ll len = strlen(str + 1);
		hash1[0] = 0;
		for (ll i = 1; i <= len; i++)
		{
			hash1[i] = hash1[i - 1] * base + (str[i] - 'a'+1);
		}
		ll ans = 0;
		for (ll i = 1; i <= L; i++)
		{
			mp.clear();
			ll cnt = 0;
			// i + j*L <--->i + (j + 1)*L - 1
			for (ll j = 0; i + (j + 1) * L - 1 <= len; j++)
			{
				cnt++;
				ull tmp = get_hash(i + j*L,L);
				mp[tmp]++;
				if (cnt >= M)
				{
					if (cnt > M)
					{
						ll tmp1 = get_hash(i + (j - M)*L, L);//前第M个
						if (mp[tmp1])
						{
							mp[tmp1]--;
							if(mp[tmp1]==0)mp.erase(tmp1);//可能中间有重复
						}
						
					}
					if (mp.size() == M)ans++;
				}
				
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

发布了16 篇原创文章 · 获赞 21 · 访问量 1327

猜你喜欢

转载自blog.csdn.net/rainbowower/article/details/104874277
今日推荐