标签:字符串hash
题意:给定m,l,一个字符串str。
我们定义一个子串为"recoverable”串 当
1、长度为 M*L
2、把这个好串分成M段,每段长度为L,且每段各不相同。
求“recoverable”串的个数,串相同位置不同也算不同。思路:预处理数组hash,hash[i]表示从i位置到尾的字符串hash值。这里数组为unsigned long long型,因为可以自动取模。然后枚举
前l个位置,每次向后翻滚(将前一个长度为l的段hash值从map中去除,将翻滚后新出现的长度为l的段hash值添加进map中),检查是
map中是否恰有n个不同的hash值,更新ans。详见代码:
/********************************************************* file name: hdu4821.cpp author : kereo create time: 2015年01月30日 星期五 18时16分00秒 *********************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<map> #include<vector> #include<stack> #include<cmath> #include<string> #include<algorithm> using namespace std; typedef unsigned long long ll; const int sigma_size=26; const int N=100+50; const int MAXN=100000+50; const int inf=0x3fffffff; const double eps=1e-8; const int mod=100000000+7; #define L(x) (x<<1) #define R(x) (x<<1|1) #define PII pair<int, int> #define mk(x,y) make_pair((x),(y)) int n,m,seed=31; char str[MAXN]; ll hash[MAXN],base[MAXN]; map<ll,int>mp; int main(){ base[0]=1; for(int i=1;i<MAXN;i++) base[i]=base[i-1]*seed; while(~scanf("%d%d",&n,&m)){ scanf("%s",str); int len=strlen(str),ans=0; hash[len]=0; for(int i=len-1;i>=0;i--) hash[i]=hash[i+1]*seed+(str[i]-'a')+1; for(int i=0;i<m && i+n*m<=len;i++){ mp.clear(); for(int j=i;j<i+n*m;j+=m) mp[hash[j]-hash[j+m]*base[m]]++; if(mp.size() == n) ans++; for(int j=i+n*m;j+m<=len;j+=m){ ll x=hash[j-n*m]-hash[j-n*m+m]*base[m]; mp[x]--; if(mp[x] == 0) mp.erase(x); x=hash[j]-hash[j+m]*base[m]; mp[x]++; if(mp.size() == n) ans++; } } printf("%d\n",ans); } return 0; }
hdu4821 String 字符串hash(bkdrhash)
标签:字符串hash
原文地址:http://blog.csdn.net/u011645923/article/details/43310143