题目来源: http://poj.org/problem?id=1200
题目大意:随机给定一段内容,并且这段内容由NC中不同字符组成,求出长度为N的子串有多少种。边界条件为,子串的个数不超过16000000。
解题思路:利用散列表的思想,首先构建散列函数,将不同子串映射成唯一的散列值存放在散列表中,这样当执行查找元素和增元素时的时间复杂度均为O(1)。利用这一特性我们可以轻松完成该题目。
注意:该题目难点在于构建散列函数,利用进制的方式保证每个子串通过散列函数得到唯一的结果。
基于以上分析代码实现如下:
/*
* Copyright: (c) 2019
*
* 文件名称: ACM1200.cpp
* 文件标识:
* 摘 要:
*
* 版 本: 1.0
* 作 者: RF_LYF
* 创建日期: 2019/5/15 13:33
*/
#include <stdio.h>
#include <string.h>
const int max_num = 16000000;
char str[max_num];
int num[256];
bool h[max_num];
int main()
{
int n ,nc;
while(~scanf("%d%d%s", &n, &nc, str))
{
int nLen = strlen(str);
int cnt = 1;
for(int i = 0; cnt <= nc; ++i)
{
if(!num[str[i]])
num[str[i]] = cnt++;
}
int sum = 0,pow=1;
for(int i = 0; i < n; ++i)
{
if(i)
pow *= nc;
sum = sum * nc + num[str[i]];
}
int ans = 0;
if(!h[sum])
{
h[sum] = true;
ans++;
}
for(int i = n; i < nLen; ++i)
{
sum -= num[str[i - n]] * pow;
sum = sum * nc + num[str[i]];
if(!h[sum])
{
h[sum] = true;
ans++;
}
}
printf("%d\n", ans);
}
return 0;
}