POJ 1200 字符串哈希

题目大意就是将一个字符串分成长度为N的字串。且每个子串中不同的字符不会超过NC个。问总共有多少个不同的子串。解题的方法把字符串中出现的 字符都用一个整数编号,然后把所有长度为N的子串对应的数字串转化为以NC作为进制的一个数字,再用哈希判断。由于题目说长度不会超过16,000,000  所以哈希长度就设为16000000就行。另外为每一个字符对应一个整数,来方便转化。


如题目中的

daababac与整数对应之后就是

12232324

然后子串

daa->122->011(因为是化为4进制,所以需要减1)->5(因为是4进制);

aab->223->112->22;

aba->232->121->25;

... ...

时间复杂度为O(string.length());
</pre><pre name="code" class="html">
</pre><pre name="code" class="html">#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <cmath>
using namespace std;
#define maxn 16000000
char s[maxn];
int ch[maxn];
int hash[maxn];

int main()
{
	int i,j,k,t,m,n,nc;
	scanf("%d%d",&n,&nc);
	cin>>s;
	
	int length = strlen(s);
	int cnt = 0;

	for(i=0;i<length;i++){
		if(!ch[s[i]])
			ch[s[i]] = cnt++;
		if(cnt==nc)
			break;
	}
	
	int ans = 0;

	for(i=0;i<length-n+1;i++){
		int sum = 0;
		for(j=i;j<i+n;j++)
			sum += sum*nc + ch[s[j]];
		if(!hash[sum]){
			ans++;
			hash[sum]=1;
		}
	}
	printf("%d\n",ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值