您的位置:首页 > 其它

HDU 4821 String(字符串哈希)

2015-10-29 10:31 435 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821

题意:

给出M和L,和一个字符串S。要求找出S的子串中长度为L*M,并且可以分成M段,每段长L,并且M段都不相同的子串个数。哈希过后,
若Hash[i]-Hash[i+L]*K[L] == Hash[j]-Hash[j+L]*k[L], 则说明串s[i...i+L-1]
和串s[j....j+L-1]是相同的。

#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
typedef unsigned long long ULL;
#define SEED 31//这个数一般为素数 如1331, 1000000007等

const int maxn = 1e5 + 100;
ULL Hash[maxn], K[maxn];
map<ULL, int> st;
char s[maxn];
int main()
{
int M, L, len;
while(~scanf("%d%d", &M, &L))
{
scanf("%s", s);
len = strlen(s);
Hash[len] = 0;
K[0] = 1;
for(int i = 1; i <= L; i++)
K[i] = K[i-1] * SEED;
for(int i = len-1; i >= 0; i--)
{
Hash[i] = Hash[i+1]*SEED + (s[i]-'a'+1);
}
int res = 0;
for(int i = 0; i<L && i+M*L<len; i++)
{
st.clear();
for(int j = i; j < M*L+i; j+=L)
{
st[Hash[j]-Hash[j+L]*K[L]]++;
}
if(st.size() == M)
res++;
for(int j = M*L+i; j <= len-L; j+=L)
{
int head = j - M*L;
st[Hash[head]-Hash[head+L]*K[L]]--;
if(st[Hash[head]-Hash[head+L]*K[L]] == 0)
st.erase(Hash[head]-Hash[head+L]*K[L]);
st[Hash[j]-Hash[j+L]*K[L]]++;
if(st.size() == M)
res++;
}
}
printf("%d\n", res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: