如何實現加入收藏、設為首頁、儲存到桌面的方法功能
阿新 • • 發佈:2020-07-25
字串雜湊
將一串字串對映為一個唯一對應的整數,將字串的比較(O(n))化簡為(O(1))
雜湊:將一個字串看作一個p進位制數再模上q
abcabcdefg
1.2.3.1.2.3.4.5.6.7.
=(1*p^9+2*p^8+3*p^7+1*p^6+2*p^5+3*p^4+4*p^3+5*p^2+6*p^1+7*p^0)%q
=hash值(屬於0~q-1)
當p取131、13331 q取2^64 (unsigned long long)時重複率最小
abd
(1.2.3)131
=1*131^2+2*131^1+4*131^0
=hash('abd')
會溢位int 但是若命做ULL 相當於自動取模2^64
一般在使用中我們會存下字首值
要求hash('abcde')
會先存下 h[0]=0
hash('a')
hash('ab')
hash('abc')
hash('abcd')=hash('abc')*131+4
所以hash(i)與hash(i+1)之間存在一個遞推式hash(i+1)=hash(i)*131+strlen(i+1)
若要求
L R
。。。。。。。。。。
h(L-R)=h(R)-h(L-1)*131^(R-L+1)
這裡令131^(R-L+1)=p[R-L+1]
//板子 const int maxn=1e6+5,base=131; char s[maxn]; ULL h[maxn],p[maxn]; ULL gethash(int l,int t) { return h[r]-h[l-1]*p[r-l+1]; } void init() { p[0]=1; for(int i=1;i<=maxn;i++) p[i]=p[i-1]*base; } int main () { init(); scanf("%s",s+1); int len=strlen(s+1); h[0]=0; for(int i=1;i<=len;i++) h[i]=h[i-1]*base+str[i]-'a'+1; cin>>………………………… }
例1 https://vjudge.net/problem/HDU-1686
Oulipo
#include<iostream> #include<cstring> using namespace std; typedef unsigned long long ULL; const int maxn=1e4+5,base=131; char str1[maxn],str2[1000005]; ULL h[1000005],p[1000005],str; int n1,n2,cnt; ULL gethash(int l, int r) { return h[r]-h[l-1]*p[r-l+1]; } void init() { p[0]=1; for(int i=1;i<=1000005-1;i++) p[i]=p[i-1]*base; } int main() { init(); int n; cin>>n; while(n--) { h[0]=0;str=0;cnt=0; scanf("%s",str1+1); //getchar(); scanf("%s",str2+1); n1=strlen(str1+1);n2=strlen(str2+1); for(int i=1;i<=n1;i++) str=str*base+(ULL)str1[i]; for(int i=1;i<=n2;i++) h[i]=h[i-1]*base+(ULL)str2[i]; for(int i=1;i<=n2-n1+1;i++) if (str==gethash(i,i+n1-1)) cnt++; cout<<cnt<<endl; } return 0; }
例二 https://vjudge.net/problem/POJ-2406
Power Strings
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef unsigned long long ULL;
const int maxn=1e6+5,base=131;
int cnt,flag;
char s[maxn];
ULL h[maxn],p[maxn];
void init()
{
p[0]=1;
for(int i=1;i<maxn;i++)p[i]=p[i-1]*base;
}
int main ()
{
init();
while(scanf("%s",s+1))
{
int len=strlen(s+1);
if(s[1]=='.'&&len==1)break;
cnt=0;h[0]=0;
for(int i=1;i<=len;i++)
h[i]=h[i-1]*base+s[i];
for(int i=1;i<=len;i++)
{
if(len%i!=0)continue;flag=1;
for(int j=i;j<=len;j+=i)
{
if(h[j]-h[j-i]*p[i]!=(ULL)h[i])
{flag=0;break;}
}
if(flag!=0){cnt=i;break;}
}
cout<<len/cnt<<endl;
}
return 0;
}
例三 https://vjudge.net/problem/HDU-4821
String
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef unsigned long long int ULL;
const int maxn=1e5+5,base=131;
int m,l,len,ans;
char s[maxn];
ULL h[maxn],p[maxn];
map<ULL,int>mm;
ULL gethash(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
void init()
{
p[0]=1;
for(int i=1;i<maxn;i++)p[i]=p[i-1]*base;
}
int main()
{
init();
while(scanf("%d%d",&m,&l)!=EOF)
{
cin>>s+1;
len=strlen(s+1);h[0]=0;ans=0;
for(int i=1;i<=len;i++)
h[i]=h[i-1]*base+s[i]-'a'+1;
for(int i=1;i<=l&&i+m*l-1<=len;i++)
{
mm.clear();
for(int j=i;j<i+m*l;j+=l)
mm[(ULL)gethash(j,j+l-1)]++;
if(mm.size()==m)ans++;
for(int j=i+m*l;j+l-1<=len;j+=l)
{
mm[(ULL)gethash(j,j+l-1)]++;
mm[(ULL)gethash(j-m*l,j-m*l+l-1)]--;
if(mm[(ULL)gethash(j-m*l,j-m*l+l-1)]==0)mm.erase((ULL)gethash(j-m*l,j-m*l+l-1));
if(mm.size()==m)ans++;
}
}
cout<<ans<<endl;
}
return 0;
}