题意:就是有一个字符串S,要求找到符合以下几种情况S的子串的个数.
情况1: 该子串的长度为L*M
请况2: 该子串的字串被分为M个,在该M个子子串中不存在相同.
(子串不同:出发的下标不同)
解题思路:
对于该问题的核心有两点:因为总串的长度比较大,所以判段字符串时否出现相同,不可能用平常的比较方法,第二如何判断两个相同的字符串到底在那个子串中。
对于第一点,我们可以用字符串hash函数来解决。
对于第二点,我们先算出下标[0,L)的所有子串的请况,那么[L,|s|- L*M]的请况可以根据之前算过的来推出。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <map>
#include <math.h>
using namespace std;
#define MAXSZ 100010
#define MOD 100003
typedef unsigned int ul;
typedef struct node{
node(){
}
node(ul hanum){
//s = key;
hashnum = hanum;
}
// string s;
ul hashnum;
};
bool vis0[MAXSZ],vis1[MAXSZ];
char str[MAXSZ];
int hasharr[MAXSZ],cnt,indexs[MAXSZ];
int M,L;
node vt[MAXSZ];
vector<int>vt1[MAXSZ];
map<int,int>mp[MAXSZ];
//inline ul BKDRHash(char *str){
// ul seed = 31; // 31 131 1313 13131 etc..
// ul hash = 0;
//
// while (*str)
// {
// hash = hash * seed + (*str++);
// }
//
// return (hash & 0x7FFFFFFF);
//}
void init(){
cnt = 0;
//memset(ff,0,sizeof(ff));
//memset(vis2,0,sizeof(vis2));
for(int i=0;i<MAXSZ;++i){
if(mp[i].size()){
mp[i].clear();
}
}
}
int hashit(char *key,ul hashnum){
int ind = hashnum%MOD;
while(vis0[ind]){
if(vt[ind].hashnum!=hashnum){
ind++;
}
// else if(vt[ind].s!=key){
// ind++;
// }
else
break;
if(ind==M){
ind%=M;
}
}
if(!vis0[ind]){
//vt[ind].s = key;
vt[ind].hashnum = hashnum;
vis0[ind] = true;
hasharr[cnt++] = ind;
}
return ind;
}
void prepro(){
char *p0 = str;
char *p1 = str;
char cc;
ul hash = 0;
ul seed = 31;
ul hashnum;
ul tmphs0;
int ind = 0,ind1 = 0;
tmphs0 = 1;
for(;ind<L;++ind){
hash = hash*seed +(*p1++);
//hash %= MOD;
if(ind){
tmphs0 = (tmphs0*seed);
}
}
hashnum = hash&0x7FFFFFFF;
//cc = (*p1);
//(*p1) = 0;
//ind = hashit(p0,hashnum);
//(*p1) = cc;
//vt1[ind].push_back(0);
indexs[0] = hashnum;
while(*p1){
hash = ((hash - tmphs0*(*p0++)));
hash = (hash*seed +(*p1++));
cc = (*p1);
++ind1;
// (*p1) = 0;
// ind = hashit(p0,hash&0x7FFFFFFF);
//(*p1) = cc;
//vt1[ind].push_back(ind1);
indexs[ind1] = hash&0x7FFFFFFF;
}
}
int solve(){
// memset(vis1,false,sizeof(vis1));
// memset(vis2,false,sizeof(vis2));
int len = (int)strlen(str);
int ans ;
int sz;
int tmp0,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6;
int up = len - (L*M);
ans = 0;
// for(int i=0;i<cnt;++i){
// tmp0 = hasharr[i];
// sz = (int)vt1[tmp0].size();
// for(int j=0;j<sz;++j){
// for(int k=j+1;k<sz;++k){
// tmp3 = vt1[tmp0][j];
// tmp4 = vt1[tmp0][k];
// tmp1 = (tmp4 - tmp3);
// if(tmp1%L==0){
// tmp2 = tmp1/L;
// if(tmp2+1<=M){
// for(int h=0;h<=up;++h){
// if(h>tmp3)break;
// if((tmp3-h)%L==0&&(tmp4-h)%L==0){
// //tmp5 = (tmp3-h)/L+1;
// //tmp6 = (tmp4 - h)/L+1;
//
// if(!vis1[h]){
// vis1[h] = true;
// --ans;
// }
// }
// }
// }
// }
// }
// }
// }
for(int i=0;i<L&&i<=up;++i){
//int ss = 0;
for(int k=i,j=0;j<M;++j,k+=L){
tmp0 = indexs[k];
if(mp[i].count(tmp0)){
//++vis2[tmp0];
++mp[i][tmp0];
//--ans;
//break;
}
else {
// ++ans;
// ff[ss++] = tmp0;
//++ff[i];
//++vis2[tmp0] ;
mp[i].insert(pair<int,int>(tmp0,1));
}
}
if(mp[i].size()==M){
++ans;
}
}
int ML = (M-1)*L;
for(int i=L;i<=up;++i){
tmp2 = i%L;
tmp0 =indexs[i-L];
--mp[tmp2][tmp0];
//--vis2[tmp0];
//if(!vis2[tmp0])
//ff[i] = ff[i-L];
if(!mp[tmp2][tmp0]){
mp[tmp2].erase(tmp0);
}
//--ff[i];
tmp1 = ML;
tmp0 = indexs[i+ML];
if(mp[tmp2].count(tmp0)){
// ++vis2[tmp0];
++mp[tmp2][tmp0];
}
else {
//[tmp0];
mp[tmp2].insert(pair<int,int>(tmp0,1));
//++ff[i];
// ++ans;
if(mp[tmp2].size()==M){
++ans;
}
}
}
return ans;
}
void clear(){
// for(int i=0;i<cnt;++i){
// if(vt1[i].size()){
// vt1[i].clear();
// }
// }
}
int main(){
// for(int i=100000;;++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;
// }
// }
while(scanf("%d%d",&M,&L)!=EOF){
init();
scanf("%s",str);
prepro();
int ans = solve();
printf("%d\n",ans);
// clear();
}
return 0;
}