- 常用哈希函数,seed=131,初始化阶数组,方便等阶后比较,初始化字符串,比较时只需要看差值。
- 逆向初始化字符串,使当前元素在差值中。
- 利用集合的大小是否符合要求判断是否有重复。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<vector>
#include<fstream>
#include<list>
#define ms(s) memset(s,0,sizeof(s))
#define pri(mark,i) printf("%s: %d\n",mark,i)
#define prs(mark,s) printf("%s: %s\n",mark,s)
#define prd(mark,d) printf("%s: %lf\n",mark,d)
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
map<ULL,int>maps;
#define L 100000
int seed = 131;
ULL base[L+5];
ULL hv[L+5];
char str[L+5];
int len;
void initBase()
{
base[0] = 1;
for(int i = 1; i <= L; ++i)
base[i] = base[i-1]*seed;
}
void initHv()
{
len = strlen(str);
hv[len] = 0;
for(int i = len-1; i >= 0; --i)
hv[i] = hv[i+1]*seed + str[i];
}
ULL getHash(int x, int l)
{
return hv[x] - hv[x+l]*base[l];
}
int main()
{
int m,l;
int countt;
initBase();
int i;
int j,k;
ULL t;
pair<ULL,int>p;
map<ULL,int>::iterator it;
while(scanf("%d%d",&m,&l) != EOF)
{
scanf("%s",str);
countt = 0;
initHv();
i = 0;
while(i < l && i < len - m*l)
{
maps.clear();
j = i;
k = j + m*l;
for(int c = 1; c <= m; ++c)
{
t = getHash(j,l);
// pri("t",t);
it = maps.find(t);
if(it == maps.end())
{
p.first = t;
p.second = 1;
maps.insert(p);
}
else
(it->second)++;
j+=l;
}
if(maps.size() == m)
{
countt++;
// pri("countt",countt);pri("i",i);pri("j",i);
}
j = i + l;
k += l;
while(k <= len)
{
t = getHash(j-l,l);
maps[t]--;
if(maps[t] == 0)
maps.erase(t);
t = getHash(k-l,l);
it = maps.find(t);
if(it == maps.end())
{
p.first = t;
p.second = 1;
maps.insert(p);
}
else
(it->second)++;
if(maps.size() == m)
{
countt++;
// pri("countt",countt);pri("i",i);pri("j",j);
}
j += l;
k += l;
}
++i;
}
printf("%d\n",countt);
}
return 0;
}