Hdu 4821 (字符串hash+map)

题目链接https://vjudge.net/problem/HDU-4821

题意:给定字符串S ,询问用几个子串满足 :

1.长度为n*len  。

2. n个子串都不相同。

题解:倒序hash将S第i位的字符变成ull,利用map维护每个子串,遍历的时候只需要去掉开头小串然后加上后面一个小串就可以实现整个字符的遍历。

Ac 代码:

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int M=1e5+5;
typedef unsigned long long ull;
ull has[M],l[M],tmp;
map<ull,int>mp;
char str[M];
int n,len,ans;
int base=31;
int main(){
l[0]=1;
for(int i=1;i<M;i++) l[i]=l[i-1]*base;
while(~scanf("%d %d",&n,&len)){
scanf("%s",str);
int len1=strlen(str);
has[len1]=0;
for(int i=len1-1;i>=0;i--){
has[i]=has[i+1]*base+str[i]-'a'+1; //将第i为以后的字符串变成ull值;
}
ans=0;
for(int i=0;i<len&&i+n*len<=len1;i++){ //对每一个长度为 n*len的子串进行判断;
mp.clear();
for(int j=i;j<i+n*len;j+=len){ //判断该 i+n*len 段子串是否符合每个子串都不同的条件;
tmp=has[j]-has[j+len]*l[len];
mp[tmp]++;
}
if(mp.size()==n) ans++; //符合种类加一;
for(int j=i+n*len;j+len<=len1;j+=len){ //以len为单位每次划出一个len 在末尾加上一个len
tmp=has[j-n*len]-has[j-(n-1)*len]*l[len]; // 如果此时还满足mp.size()==n ans++;
mp[tmp]--;
if(mp[tmp]==0) mp.erase(tmp);
tmp=has[j]-has[j+len]*l[len];
mp[tmp]++;
if(mp.size()==n) ans++;
}
}
cout<<ans<<endl;
}
return 0;
}
上一篇:Javascript进阶篇——( JavaScript内置对象---上-Date,string,charAt,indexOf,split,substring,substr)笔记整理


下一篇:hdu 2610 2611 dfs的判重技巧