HDU 4821 String(字符串Hash)

String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3895    Accepted Submission(s): 1174


Problem Description
Given a string S and two integers L and M, we consider a substring of S as “recoverable” if and only if
  (i) It is of length M*L;
  (ii) It can be constructed by concatenating M “diversified” substrings of S, where each of these substrings has length L; two strings are considered as “diversified” if they don’t have the same character for every position.

Two substrings of S are considered as “different” if they are cut from different part of S. For example, string "aa" has 3 different substrings "aa", "a" and "a".

Your task is to calculate the number of different “recoverable” substrings of S.
 

Input
The input contains multiple test cases, proceeding to the End of File.

The first line of each test case has two space-separated integers M and L.

The second ine of each test case has a string S, which consists of only lowercase letters.

The length of S is not larger than 10^5, and 1 ≤ M * L ≤ the length of S.
 

Output
For each test case, output the answer in a single line.
 

Sample Input
 
  
3 3abcabcbcaabc
 

Sample Output
 
  
2
 

Source
 

Recommend
liuyiding


【思路】

把子字符串分为m段,每段长度为l,要求的是这样的子字符串个数:它的m段都是不同的。

1、字符串匹配方面,可以用字符串哈希,哈希值相同则字符串相同。

2、如果是枚举子串头尾,复杂度则为O(N²),不可行。我们可以将考虑的子串分为l类,每一类都刚好差别一小段长度为l字符串,所以整个子串就可以通过哈希值加减改变,每次去头添尾即可,复杂度为O(N)级别。


【代码】

//************************************************************************
// File Name: HDU_4821.cpp
// Author: Shili_Xu
// E-Mail: [email protected] 
// Created Time: 2018年02月24日 星期六 20时53分34秒
//************************************************************************

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;

typedef unsigned long long ull;
const int MAXN = 1e5 + 5, BASE = 31;

int m, l;
char s[MAXN];
ull hsh[MAXN], p[MAXN];
map<ull, int> st;

void init()
{
	int len = strlen(s);
	hsh[0] = (ull)(s[0] - 'a');
	p[0] = (ull)1;
	for (int i = 1; i < len; i++) {
		hsh[i] = hsh[i - 1] * BASE + (ull)(s[i] - 'a');
		p[i] = p[i - 1] * BASE;
	}
}

ull get_hash(int l, int r)
{
	if (l == 0) return hsh[r];
	return (hsh[r] - hsh[l - 1] * p[r - l + 1]);
}

int main()
{
	while (scanf("%d %d", &m, &l) == 2) {
		scanf("%s", s);
		init();
		int len = strlen(s), ans = 0;
		for (int i = 0; i < l; i++) {
			int left = i, right = i + m * l - 1;
			if (right >= len) break;
			st.clear();
			for (int j = 0; j < m; j++) st[get_hash(left + j * l, left + j * l + l - 1)]++;
			if (st.size() == m) ans++;
			while (right + l < len) {
				left += l; right += l;
				st[get_hash(left - l, left - 1)]--;
				if (st[get_hash(left - l, left - 1)] == 0) st.erase(get_hash(left - l, left - 1));
				st[get_hash(right - l + 1, right)]++;
				if (st.size() == m) ans++;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/shili_xu/article/details/79438355