題意:
判斷字符串中有多少個長度爲N的子串,且字符總類不會超過NC種。
解題思路:
字符串hash
注意:
無
//字符串hash
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <set>
#include <math.h>
using namespace std;
typedef long long LL;
#define MAXSZ 1700000
#define MOD 1000003
set<LL> st;
set<LL>::iterator itr;
char str[MAXSZ];
int N,NC;
void clear(){
if(st.size()){
st.clear();
}
}
inline LL BKDRHash(char *str)
{
LL seed = 31; // 31 131 1313 13131 etc..
LL hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash /*& 0x7FFFFFFF*/);
}
int solve(char *s){
int ans = 1;
char *p0 = s,*p1 = s+N;
LL hash = 0,tmp,hash1 = 1;
LL seed = 31;
char cc = (*p1);
(*p1) = 0;
hash = BKDRHash(p0);
(*p1) = cc;
tmp = hash&0x7FFFFFFF;
st.insert(tmp);
for(int i=1;i<N;++i){
hash1*=seed;
}
while((*p1)){
hash = hash - hash1*(*p0);
//++p1;
hash = hash*seed + (*p1);
tmp = hash&0x7FFFFFFF;
itr = st.find(tmp);
if(itr==st.end()){
st.insert(tmp);
++ans;
}
// if(!st.count(tmp)){
// st.insert(tmp);
// ans++;
// }
++p1;
++p0;
}
return ans;
}
int main(){
int T;
// for(int i=1000000;;i++){
// bool flag = true;
// for(int j=2;j<=sqrt(i*1.0);j++){
// if(i%j==0){
// flag = false;
// break;
// }
// }
// if(flag){
// printf("%d\n",i);
// break;
// }
//}
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&NC);
scanf("%s",str);
int ans = solve(str);
printf("%d\n",ans);
clear();
}
return 0;
}