现在的位置: 首页 > 综合 > 正文

hdu 4821 String

2019年02月09日 ⁄ 综合 ⁄ 共 1629字 ⁄ 字号 评论关闭

这两天做了几道题,跑来总结总结。

这道题到手先是读傻了。思来想去不得正解。百度了一下看到字符串Hash,立马关掉。又是一个陌生的术语。

找了些资料后先是做了poj1200,上手了字符串Hash。换句话说是BKDRHash。

简单的介绍一下。

unsigned int BKDRHash(char * str){
	unsigned int base = 31; //131 1331 13331 ...
	unsigned int hash = 0;
	while (*str){
		hash = hash*base + (*str++);
	}
	return hash;
}

这个函数可以把一个字符串转化成一个数字。
先去感受一下吧。

当你对BKDRHash有了一定概念以后。进入正文。

----------------------------------------------------------------------------------------------------------------------

遍历开头,也就是前L个字符。

然后把每L个字符转换成一个数字保存在数组中。

问题就转化成为求一个数组中连续的不相同的长度为m的子串。

用一个小技巧预处理一下可以让字符转化的复杂度降为O(n)。

求字符串前i个字符的Hash值。得到num[i]。

那么 i- j 对应的字符串所代表的数字为 num[j]-num[i]*p[j-i+1];

p为base对自己的累乘。不明白就看代码,一目了然。

问题传化后见变成了一个简单计数问题了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
typedef unsigned __int64 ULL;
const int N = 1e5 + 10;
char s[N];
ULL num[N];
ULL p[N];
int m, l;
map<ULL, int> mp;
ULL base = 31;
ULL t[N];
int cnt;
int main(){
	p[0] = 1;
	for (int i = 1; i < N; i++)
		p[i] = p[i - 1] * base;
	while (~scanf("%d%d%s", &m, &l, s)){
		int len = strlen(s);
		int i, j;
		ULL Hash = 0;
		
		//mp.clear();
		memset(num,0,sizeof(num));
		for (i = 1; i <= len ; ++i){
			num[i] = num[i - 1] * base + s[i-1] - 'a';

		}
		int ml = m*l;
		int ans = 0;
		for (i = 0; i < l; ++i){
			int tmp = 0;
		
			cnt = 0;
			for (j = i + 1; j + l - 1 <= len; j += l){
				ULL Hash = num[j + l - 1] - num[j - 1] * p[l];
				t[cnt++] = Hash;

				/*//	cout << Hash << endl;
					if (mp[Hash] == false)
					tmp++;
					else{
					mp.clear();
					if (tmp >= m){
					ans += tmp - m + 1;
					tmp = tmp%m;
					j -= tmp*l;
					tmp = 0;
					}
					else tmp = 1;
					}
					mp[Hash] = true;


					}
					if (tmp >= m)ans += tmp - m + 1;
					//	cout << endl;*/
			}
			mp.clear();
			
			for (j = 0; j < cnt; j++){
				if (mp.find(t[j]) == mp.end())
				{
					mp[t[j]] = j;
					tmp++;
				}
				else if (j - mp[t[j]] + 1 > m){
					mp[t[j]] = j;
					tmp++;
				}
				else if(tmp>=m){
					ans += tmp - m + 1;
					j = mp[t[j]];
					tmp = 0;
					mp.clear();
				}
				else{
					j = mp[t[j]];
					tmp = 0;
					mp.clear();
				}
			}
			if (tmp >= m){
				ans += tmp - m + 1;
			}
		}

		printf("%d\n" , ans );
	}
	return 0;
}
/*
3 3
qwertyuiopasqwefghjkl
*/

抱歉!评论已关闭.