题目大意就是给你一个字符串,由NC种字母组成,要你求它有多少个长度为N的且不同的子串
题目是放在hash和并查集的专栏里,于是一开始拿到题便往并查集的方向去想,想了半天想不出来,一看题解,哈希?exm?
认认真真的看了大佬的思路,恍然大悟,牛逼,牛逼,居然能想到转化为进制来做,一举两得啊,一来hash函数都不用写,开个数组就好了,二来代码超好写,两个for循环就能搞定
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int nmax=16000005;
int vis[30]; //总共也才26个字母,30够了
int hashh[nmax];
char s[nmax];
int main()
{
int N,M;
while(~scanf("%d%d%s",&N,&M,s))
{
memset(vis,0,sizeof vis);
memset(hashh,0,sizeof hashh);
int cnt=0;
vis[s[0]-'a']=cnt++; 这个字母对应M进制下的cnt
int n=strlen(s);
for(int i=1;i<n;i++)
if(!vis[s[i]-'a'])
vis[s[i]-'a']=cnt++;
int ans=0;
for(int i=0;i<=n-N;i++)
{
int sum=0;
for(int j=i;j<i+N;j++)
sum=sum*M+vis[s[j]-'a']; 求出M进制下的这个子串所对应的数值,一定是唯一的,不会有两个不同的串转化后的值相等
if(!hashh[sum])
{
ans++;
hashh[sum]++;
}
}
printf("%d\n",ans);
}
return 0;
}