题意:给一个串,问存在多少个子串长度为m*l,其中m段长度为l的子子串各不相同。
思路:哈希。将每段长度为l的子串哈希,就可以迅速比较是否相同,然后插入到map中检查。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#include <sstream>
#define INF 1000000000
#define ll long long
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
using namespace std;
#define maxlen 100010
#define ull unsigned long long
char str[maxlen];
const int x=123;
ull xn[maxlen],H[maxlen],hash[maxlen];
int main(){
xn[0]=1;
for(int i=1;i<=100000;i++)xn[i]=xn[i-1]*x;
int m,l;
while(cin>>m>>l){
scanf("%s",str);
int siz=strlen(str);
H[siz]=0;
for(int i=siz-1;i>=0;i--)H[i]=H[i+1]*x+(str[i]-'a');
hash[siz-l]=H[siz-l];
for(int i=siz-l-1;i>=0;i--)hash[i]=H[i]-H[i+l]*xn[l];
int ans=0;
for(int i=0;i<l;i++){
map<ull,int> mp;
int cnt=0;
for(int j=i;j+l<=siz;j+=l){
if(j/l>=m){
mp[hash[j-l*m]]--;
if(mp[hash[j-l*m]]==0)mp.erase(hash[j-l*m]);
}
mp[hash[j]]++;
if(mp.size()==m)ans++;
}
}
cout<<ans<<endl;
}
return 0;
}