HASH算法小结

时间:2022-09-28 22:40:40

一、简述

HASH算法的本质是特征提取——将某种不太好表示的特征,通过某种压缩的方式映射成一个值。这样,就可以优雅解决一部分难以解决的特征统计问题。

同时考虑到hash算法的本质是个概率算法,因此并不能保证所有的数据都不发生冲突<冲突是指两个不同的特征计算出了同一个HASH值>,因此可以考虑使用双hash的形式,使用两个不同的HASH算法,算出来的HASH值来表示一个特征量——pair<ull,ull>就是一种实现方式。

一种常用的hash算法来自一一个递推式:hash[i] = ( hash[i-1] * HASH_P + val[i] ) % HASH_MOD;

这种方式实际上可以比喻成为一个在%HASH_MOD意义下P进制的大数,且每次都添加一个新的个位数进入hash值中。

因此,实际使用中可以支持%HASH_MOD意义下的加法、减法。

另外hash算法好想好写,可以分外暴力的解决相当部分的问题。<甚至可以直接使用优雅的#define来完成模板的编写>

二、提取树的特征

Similarity of Subtrees
https://vjudge.net/problem/Aizu-2784

题意:给出一颗树,询问以1作为树根的树中,结构相同的子树个数有多少对。结构相同定义为,以某点为根节点,其以下每层的的节点个数都与另一节点相应属性相同。

Define the depth of a node in a rooted tree by applying the following rules recursively:

  • The depth of a root node is 0.
  • The depths of child nodes whose parents are with depth dd are d+1d+1.

Let S(T,d)S(T,d) be the number of nodes of TT with depth dd. Two rooted trees TT and T′T′ are similar if and only if S(T,d)S(T,d) equals S(T′,d)S(T′,d) for all non-negative integer dd.

You are given a rooted tree TT with NN nodes. The nodes of TT are numbered from 1 to NN. Node 1 is the root node of TT. Let TiTi be the rooted subtree of TT whose root is node ii. Your task is to write a program which calculates the number of pairs (i,j)(i,j)such that TiTi and TjTj are similar and i<ji<j.

https://cn.vjudge.net/problem/Aizu-2784

题解:可以发现,子树的结构实际上是可以通过HASH算法形式的递推得到——hash[now] = (∑(hash[child]) * HAHS_P + num[now])%HASH_MOD

该递推式实际上表现了hash值的加法过程。

则,如果支持dfs且不爆栈的话,可以使用dfs一发搞定,相当的优雅。

但是反过来,如果不支持dfs,则必须用bfs的方式来搞定树的遍历和递推,实际上也很好想,因为记录了每个节点的父节点,也记录了每个节点的子节点数量,就可以很容易的计算出来某个节点的所有子节点是否已经完成了递推计算。提供两个版本的代码:dfs实现和bfs实现。

dfs:

#include<math.h>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include <iostream>
using namespace std; #define ull unsigned long long
#define hash1(x,b) (((ull)x * HASH_P1 + b)%HASH_MOD1)
#define hash2(x,b) (((ull)x * HASH_P2 + b)%HASH_MOD2)
#define ll long long
const int MAXN = ;
const ull HASH_MOD1 = ;
const ull HASH_MOD2 = ;
const ull HASH_P1 = ;
const ull HASH_P2 = ; #define veci vector<int>
#define pp pair<ull,ull>
veci G[MAXN];
int n;
map<ull,int> mapp;
ll ans; pp dfs_count(int now,int father){ // pp ret = make_pair<ull.int>(0ull,0);
pp ret;
ret.first = ret.second = ;
int len = G[now].size();
for(int i=;i<len;++i){
int tar = G[now][i];
if(tar == father)continue;
pp tmp = dfs_count(tar,now);
ret.first += tmp.first;
ret.second += tmp.second;
}
ret.first %= HASH_MOD1;
ret.second %= HASH_MOD2;
ret.first = hash1(ret.first,);
ret.second = hash2(ret.second,);
ull hash_tmp = ret.first * HASH_MOD1 + ret.second;
if(mapp.count(hash_tmp)){
int tmp = mapp[hash_tmp];
ans += tmp;
mapp[hash_tmp] = tmp+;
}else{
// mapp.insert(make_pair(hash_tmp,1));
mapp[hash_tmp] = ;
} return ret;
} void init(){
ans = ;
for(int i=;i<n+;++i)G[i].clear();
mapp.clear();
for(int i=;i<n;++i){
int a,b;
cin>>a>>b;
G[a].push_back(b);
G[b].push_back(a);
} dfs_count(,);
cout<<ans<<"\n";
} int main(){ cin.sync_with_stdio(false);
while(cin>>n)init(); return ;
}

bfs:

#include<math.h>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include <iostream>
using namespace std; #define ull unsigned long long
#define hash1(x,b) (((ull)x * HASH_P1 + b)%HASH_MOD1)
#define hash2(x,b) (((ull)x * HASH_P2 + b)%HASH_MOD2)
#define ll long long
const int MAXN = ;
const ull HASH_MOD1 = ;
const ull HASH_MOD2 = ;
const ull HASH_P1 = ;
const ull HASH_P2 = ; #define veci vector<int>
#define pp pair<ull,ull>
veci G[MAXN];
int n;
map<ull,int> mapp;
ll ans;
ull hash_tmp;
int fa[MAXN];
pp anss[MAXN];
int times[MAXN]; void bfs(){
queue<int>que;
que.push();
for(int i=;i<G[].size();++i)fa[G[][i]] = ;
while(!que.empty()){
int now = que.front();
que.pop();
times[now] = ;
for(int i=;i<G[now].size();++i){
int tar = G[now][i];
if(tar==fa[now])continue;
times[now] ++;
fa[tar] = now;
que.push(tar);
}
}
}
void deal(){ queue<int> que;
for(int i=;i<=n;++i){
// G[i].size() == 1;
if(times[i] == )
que.push(i);
// anss[i] = make_pair(hash1(0,1),hash2(0,1));
} while(!que.empty()){
int now = que.front();
que.pop();
// if(times[now])continue; // cout<<"check_seq: "<<now; times[fa[now]]--;
if(times[fa[now]] == )que.push(fa[now]); int len = G[now].size();
// anss[now] = make_pair(0,0);
for(int i=;i<len;++i){
int tar = G[now][i];
if(tar == fa[now])continue;
anss[now].first += anss[tar].first;
anss[now].second += anss[tar].second;
}
anss[now].first %= HASH_MOD1;
anss[now].second %= HASH_MOD2;
anss[now].first = hash1(anss[now].first,);
anss[now].second = hash2(anss[now].second,); ull hash_tmp = anss[now].first * HASH_MOD1 + anss[now].second; // cout<<" "<<hash_tmp<<endl; if(mapp.count(hash_tmp)){
int tmp = mapp[hash_tmp];
ans += tmp;
mapp[hash_tmp] = tmp+;
}else{
mapp[hash_tmp] = ;
}
times[now] = ;
}
} void init(){
memset(anss,,sizeof(anss));
memset(times,,sizeof(times));
ans = ;
for(int i=;i<n+;++i)G[i].clear();
mapp.clear();
for(int i=;i<n;++i){
int a,b;
cin>>a>>b;
G[a].push_back(b);
G[b].push_back(a);
} bfs();
deal(); cout<<ans<<"\n";
} int main(){ cin.sync_with_stdio(false);
while(cin>>n)init(); return ;
}

三、提取连续子串的特征

Stammering Aliens

https://cn.vjudge.net/problem/UVALive-4513

题意:给一个长串,问至少出现m次的最长连续字串的长度和出现的最右一个字串的起始的位置是多少。

题解:

这道题实际上时刘汝佳蓝书上的一道例题,在做的过程中表现了用到了hash串做减法的思路。

考虑答案中的两个量:最长长度和最右起始位置。最长长度具有某种意义上的单调性:如果长度为n的字串可以符合题目条件,则n-1的也可以(n>1);因此考虑使用二分的形式来枚举字串的长度。最右起始位置可以直观的求解。

考虑递推式:hash[i] = (hash[i-1] * HAHS_P + str[i]) % HASH_MOD

若简化为十进制数字则可以有如下样例:
3129741938274  求字串由2到7的hash值

hash[7] = 31297419

hash[2] = 312

hahs[2-7] = 97419

观察可得:hash[2-7] = hash[7] - hash[2]*10^(7-2);

则实际上只要保证上式在%HASH_MOD意义上成立即可。

#include<bits/stdc++.h>
using namespace std; #define ll long long
#define ull unsigned long long
#define pp pair<ull,ull>
const int MAXN = ;
const ull HASH_P1 = ;
const ull HASH_P2 = ;
const ull HASH_MOD1 = ;
const ull HASH_MOD2 = ;
#define hash1(x,b) (((ull)x * HASH_P1 + b) % HASH_MOD1)
#define hash2(x,b) (((ull)x * HASH_P2 + b) % HASH_MOD2)
#define get_next_hash(tmp,b) (make_pair(hash1(tmp.first,b),hash2(tmp.second,b))) pp hashs[MAXN];
pp hash_hex[MAXN]; int m; char str[MAXN];
int str_len,pos; ull mapp[MAXN];
int anss[MAXN];
int mapp_num; bool cmp(int a,int b){
if(mapp[a] == mapp[b])return a<b;
return mapp[a]<mapp[b];
} bool check(int length){
pos = -;
mapp_num = ;
anss[mapp_num] = mapp_num;
mapp[mapp_num++] = hash1(hashs[length-].first,hashs[length-].second);
for(int i=length;i<str_len;++i){
ull a = hashs[i].first;
ull tmp = (hashs[i-length].first * hash_hex[length].first)%HASH_MOD1;
a-= tmp;
a+=HASH_MOD1;a%=HASH_MOD1; ull b = hashs[i].second;
tmp = (hashs[i-length].second * hash_hex[length].second)%HASH_MOD2;
b -= tmp;
b+=HASH_MOD2;b%=HASH_MOD2; ull hash_tmp = hash1(a,b);
anss[mapp_num] = mapp_num ;
mapp[mapp_num++] = hash_tmp;
}
sort(anss,anss+mapp_num,cmp);
int cntt = ;
if(m == )pos = anss[];
for(int i=;i<mapp_num;++i){
if(mapp[anss[i]] == mapp[anss[i-]])cntt++;
else cntt = ;
if(cntt >= m )pos = max(pos,anss[i]);
}
return pos != -;
} int bin_search(int a,int b){
if(a == b-)return a;
int mid = (a+b)/;
if(check(mid))return bin_search(mid,b);
else return bin_search(a,mid);
} void init(){
gets(str);
str_len = strlen(str);
pp tmp = make_pair(,);
for(int i=;i<str_len;++i){
tmp = get_next_hash(tmp,str[i]);
hashs[i] = tmp;
}
int ans = bin_search(,str_len+);
check(ans);
if(ans){
printf("%d %d\n",ans,pos);
}else{
puts("none");
}
} int main(){
// pp tmp = make_pair(1,1);
hash_hex[] = make_pair(,);
for(int i=;i<MAXN;++i){
hash_hex[i] = get_next_hash(hash_hex[i-],);
}
while(~scanf("%d\n",&m)&&m)init();
return ;
}

四、统计字母出现个数

Hidden Anagrams
AIZU:https://cn.vjudge.net/problem/Aizu-1370Gym:https://cn.vjudge.net/problem/Gym-101158D
UVALive:https://cn.vjudge.net/problem/UVALive-7592

题意:给出两个字符串,求出最大的长度满足,两个字符串都包含该子串,同时两个字串包含的字母的种类和个数完全相同。

题解:思路很简单,就是枚举长度,并检查上面的字符串中是否存在能和下面的串长度相同的,HASH值一致的串。如果有,则检查通过,没有则不通过,从高往低枚举,找到第一个通过的跳出循环<也许会有个常数优化>。

此时HASH算法应当做一个简单的变化:统计某个字母出现的个数。HASH[I] = HASH[I-1] + HASH_HEX[STR[I]-'a']

此实HASH_HEX代表了HASH_P的在对HASH_MOD做膜法操作的前提下的若干次方。

这道题有4个来源可以提交,Gym和AIZU可以让N2LOGN甚至更慢的代码通过,UVALIVE允许N2的代码加入邻接链表优化通过<此时我已经开了IO挂>,HOJ。。。。。需要在进一步的取消HASH2的膜法操作。

#include<math.h>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<stdio.h>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include <iostream>
#include <limits.h>
using namespace std; #define ull unsigned long long
#define pp pair<ull,ull>
const ull MAXN = ;
#define vecu vector<ull>
#define vevi vector<int>
#define vecp vector<pp >
const ull HASH_P1 = ;
const ull HASH_P2 = ;
const ull HASH_MOD1 = ;
const ull HASH_MOD2 = ;
#define hash1(x,b) (((ull)x * HASH_P1 + b)%HASH_MOD1)
#define hash2(x,b) (((ull)x * HASH_P2 + b))
#define next_hash(tmp,b) (make_pair(hash1(tmp.first,b),hash2(tmp.second,b)))
#define add_hash(tmp,b) (make_pair((tmp.first + hash_hex[idx(b)].first) % HASH_MOD1,(tmp.second + hash_hex[idx(b)].second) ))
#define sub_hash(tmpa,tmpb) (make_pair((tmpa.first + HASH_MOD1 - tmpb.first) % HASH_MOD1 , (tmpa.second - tmpb.second) ) )
#define idx(x) (x-'a') namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror=;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,,BUF_SIZE,stdin);
if (pend==p1){IOerror=;return -;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(int &x){
bool sign=; char ch=nc(); x=;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=,ch=nc();
for (;ch>=''&&ch<='';ch=nc())x=x*+ch-'';
if (sign)x=-x;
}
inline void read(ll &x){
bool sign=; char ch=nc(); x=;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=,ch=nc();
for (;ch>=''&&ch<='';ch=nc())x=x*+ch-'';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=; char ch=nc(); x=;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=,ch=nc();
for (;ch>=''&&ch<='';ch=nc())x=x*+ch-'';
if (ch=='.'){
double tmp=; ch=nc();
for (;ch>=''&&ch<='';ch=nc())tmp/=10.0,x+=tmp*(ch-'');
}
if (sign)x=-x;
}
inline int read(char *s){
char ch=nc();if(ch == EOF)return -;
for (;blank(ch);ch=nc());
if (IOerror)return -;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=;
return ;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-;return;}
}
//getchar->read
inline void read1(int &x){
char ch;int bo=;x=;
for (ch=getchar();ch<''||ch>'';ch=getchar())if (ch=='-')bo=;
for (;ch>=''&&ch<='';x=x*+ch-'',ch=getchar());
if (bo)x=-x;
}
inline void read1(ll &x){
char ch;int bo=;x=;
for (ch=getchar();ch<''||ch>'';ch=getchar())if (ch=='-')bo=;
for (;ch>=''&&ch<='';x=x*+ch-'',ch=getchar());
if (bo)x=-x;
}
inline void read1(double &x){
char ch;int bo=;x=;
for (ch=getchar();ch<''||ch>'';ch=getchar())if (ch=='-')bo=;
for (;ch>=''&&ch<='';x=x*+ch-'',ch=getchar());
if (ch=='.'){
double tmp=;
for (ch=getchar();ch>=''&&ch<='';tmp/=10.0,x+=tmp*(ch-''),ch=getchar());
}
if (bo)x=-x;
}
inline int read1(char *s){
char ch=getchar();
for (;blank(ch);ch=getchar());
for (;!blank(ch);ch=getchar())*s++=ch;
*s=;
}
inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
//scanf->read
inline void read2(int &x){scanf("%d",&x);}
inline void read2(ll &x){
#ifdef _WIN32
scanf("%I64d",&x);
#else
#ifdef __linux
scanf("%lld",&x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void read2(double &x){scanf("%lf",&x);}
inline void read2(char *s){scanf("%s",s);}
inline void read2(char &c){scanf(" %c",&c);}
inline void readln2(char *s){gets(s);}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[],*s1;s1=s;
if (!x)*s1++='';if (x<)out('-'),x=-x;
while(x)*s1++=x%+'',x/=;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[],*s1;s1=s;
if (!x)*s1++='';if (x<)out('-'),x=-x;
while(x)*s1++=x%+'',x/=;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[],*s1;s1=s;
if (!x)*s1++='';if (x<)out('-'),x=-x;
while(x)*s1++=x%+'',x/=;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[],*s1;s1=s;
if (!x)*s1++='';if (x<)out('-'),x=-x;
while(x)*s1++=x%+'',x/=;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={,,,,,,,,,
,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>){out('.'); for (size_t i=;i<y&&x3*mul[i]<mul[y];out(''),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
//puts->write
char Out[OUT_SIZE],*o=Out;
inline void print1(int x){
static char buf[];
char *p1=buf;if (!x)*p1++='';if (x<)*o++='-',x=-x;
while(x)*p1++=x%+'',x/=;
while(p1--!=buf)*o++=*p1;
}
inline void println1(int x){print1(x);*o++='\n';}
inline void print1(ll x){
static char buf[];
char *p1=buf;if (!x)*p1++='';if (x<)*o++='-',x=-x;
while(x)*p1++=x%+'',x/=;
while(p1--!=buf)*o++=*p1;
}
inline void println1(ll x){print1(x);*o++='\n';}
inline void print1(char c){*o++=c;}
inline void println1(char c){*o++=c;*o++='\n';}
inline void print1(char *s){while (*s)*o++=*s++;}
inline void println1(char *s){print1(s);*o++='\n';}
inline void println1(){*o++='\n';}
inline void flush1(){if (o!=Out){if (*(o-)=='\n')*--o=;puts(Out);}}
struct puts_write{
~puts_write(){flush1();}
}_puts;
inline void print2(int x){printf("%d",x);}
inline void println2(int x){printf("%d\n",x);}
inline void print2(char x){printf("%c",x);}
inline void println2(char x){printf("%c\n",x);}
inline void print2(ll x){
#ifdef _WIN32
printf("%I64d",x);
#else
#ifdef __linux
printf("%lld",x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void println2(ll x){print2(x);printf("\n");}
inline void println2(){printf("\n");}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
}; char str1[MAXN];
char str2[MAXN];
int str1_len,str2_len;
pp hash_hex[MAXN];
pp str1_hash[MAXN];
pp str2_hash[MAXN]; class hash_node{
public:
ull val;int next;
};
hash_node hash_nodes[MAXN];
int hash_nodes_num;
int hash_table[MAXN];
inline int new_hash_nodes(int idx,ull key){
hash_nodes[hash_nodes_num].next = hash_table[idx];
hash_nodes[hash_nodes_num].val = key;
return hash_nodes_num++;
} inline bool hash_find_key(int idx,ull key){
int now = hash_table[idx];
while(now!=-){
if(hash_nodes[now].val == key)return true;
now = hash_nodes[now].next;
}return false;
} inline void hash_insert(int idx,ull key){
hash_table[idx] = new_hash_nodes(idx,key);
} inline void hash_clear(int idx){
hash_table[idx] = -;
} // vecu hash_table[HASH_MOD1];
// inline bool find_key(ull idx,ull key){
// int len = hash_table[idx].size();
// for(int i=0;i<len;++i){
// if(hash_table[idx][i] == key)return true;
// }return false;
// }
// inline void hash_insert(ull idx,ull key){
// hash_table[idx].push_back(key);
// }
// inline void hash_clear(ull idx){
// hash_table[idx].clear();
// } inline bool check(int length){ hash_nodes_num = ;
hash_insert(str1_hash[length-].first,str1_hash[length-].second);
for(int i=length;i<str1_len;++i){
pp tmp = sub_hash(str1_hash[i],str1_hash[i-length]);
hash_insert(tmp.first,tmp.second);
}
if(hash_find_key(str2_hash[length-].first,str2_hash[length-].second))return true;
for(int i=length;i<str2_len;++i){
pp tmp = sub_hash(str2_hash[i],str2_hash[i-length]);
// hash_insert(tmp.first,tmp.second);
if(hash_find_key(tmp.first,tmp.second))return true;
} hash_clear(str1_hash[length-].first);
for(int i=length;i<str1_len;++i){
pp tmp = sub_hash(str1_hash[i],str1_hash[i-length]);
hash_clear(tmp.first);
}
return false;
} void init(){
// for(int i=0;i<HASH_MOD1;++i)hash_table[i].clear();
memset(hash_table,-,sizeof(hash_table));
str1_len = strlen(str1);
str2_len = strlen(str2);
str1_hash[] = hash_hex[idx(str1[])];
str2_hash[] = hash_hex[idx(str2[])]; for(int i=;i<str1_len;++i)str1_hash[i] = add_hash(str1_hash[i-],str1[i]);
for(int i=;i<str2_len;++i)str2_hash[i] = add_hash(str2_hash[i-],str2[i]); int limit = min(str1_len,str2_len);
int ans = ;
for(int i=limit;i;i--){
if(check(i)){
ans = i;
break;
}
}
// cout<<ans<<"\n";
fastIO::println(ans);
} int main(){ hash_hex[] = make_pair(,);
for(int i=;i<;++i) hash_hex[i] = next_hash(hash_hex[i-],);
// while(gets(str1)&&gets(str2))init();
while(~fastIO::read(str1) && ~fastIO::read(str2))init();
// while()
return ;
}

HASH算法小结的更多相关文章

  1. 一致性hash算法小结

    把服务器的IP或者主机名作为key对2^32求余,余数一定是2^32-1,然后放到(平行映射)0~2^32次方首尾相连的环上.   理想状态下服务器会均匀分布在这个环上,当数据存储时,依然把key对2 ...

  2. 一致性 hash 算法( consistent hashing )a

    一致性 hash 算法( consistent hashing ) 张亮 consistent hashing 算法早在 1997 年就在论文 Consistent hashing and rando ...

  3. 一致性 hash 算法

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...

  4. 一致性 hash 算法( consistent hashing )

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在cache 系统中应用越来越广泛: 1 基 ...

  5. &lbrack;图论&rsqb;Floyd 算法小结

    Floyd 算法小结  By Wine93 2013.11 1. Floyd算法简介 Floyd算法利用动态规划思想可以求出任意2点间的最短路径,时间复杂度为O(n^3),对于稠密图, 效率要高于执行 ...

  6. 【转】一致性hash算法&lpar;consistent hashing&rpar;

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1  ...

  7. 一致性hash算法 - consistent hashing

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...

  8. 怎样的 Hash 算法能对抗硬件破解

    前言 用过暴力破解工具 hashcat 的都知道,这款软件的强大之处在于它能充分利用 GPU 计算,比起 CPU 要快很多.所以在破解诸如 WiFi 握手包.数据库中的口令 Hash 值时,能大幅提高 ...

  9. &lbrack;转&rsqb;一致性hash算法 - consistent hashing

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1  ...

随机推荐

  1. 使用Docker Image跑Gitlab

    下载gitlab docker镜像 docker pull gitlab/gitlab-ce:latest 启动gitlab服务 sudo docker run --detach \ --hostna ...

  2. Arrya数组添加过滤条件

    var arr = new Array(); arr.push(); arr.push(); arr.push(); var rs = arr.filter(function (value,index ...

  3. inux环境PHP7&period;0安装

    inux环境PHP7.0安装   PHP7和HHVM比较PHP7的在真实场景的性能确实已经和HHVM相当, 在一些场景甚至超过了HHVM.HHVM的运维复杂, 是多线程模型, 这就代表着如果一个线程导 ...

  4. 转:github使用教程(重装系统后遇到问题该文章帮我解决了)

    github简单使用教程 时间:2012 年 5 月 29 日 6 条评论 分类:学习笔记 , 网络 , 软件 目录 1.注册账户以及创建仓库 2.安装客户端msysgit 3.配置Git 4.提交. ...

  5. hdu 4753 Fishhead’s Little Game

    状态压缩dp解博弈问题(记忆化搜索).比赛的时候最后才开始做这道题,而且当时不知道为什么一直犯一些很2B的问题,导致没能ac,晚上看了看原先的代码,改了一下就MLE了...我原先是开的dp[1 &lt ...

  6. CentOS 7 增加磁盘分区挂载(lvm)

    1.查看主机现有磁盘情况 # fdisk -l 现在主机中存在一块8G的磁盘sdb,尚未分区挂载,所以需将磁盘进行分区挂载. 2.对磁盘进行分区 # fdisk /dev/sdb   (选择要操作分区 ...

  7. 20170831工作日记--自定义View学习

    学习了LayoutInflater的原理分析.视图的绘制流程.视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.那么下面我们就来依次 ...

  8. django-from

    构建一个表单 这是一个非常简单的表单.实际应用中,一个表单可能包含几十上百个字段,其中大部分需要预填充,而且我们预料到用户将来回编辑-提交几次才能完成操作. 我们可能需要在表单提交之前,在浏览器端作一 ...

  9. HTML5、CSS3与响应式Web设计入门&lpar;2&rpar;

    HTML5的宽泛含义开拓了Web开发的视野,增加了开发方案的多样性,同时也带给很多Web开发者不小的困惑,就是HTML5在涉及到Web某个应用领 域的开发时,到底代表了什么?本篇文章的目的就在于跟大伙 ...

  10. Eclipse中使用git提交代码,报错Testng 运行Cannot find class in classpath的解决方案

    一.查找原因方式 1.点击Project——>Clear...——>Build Automatically 2.查看问题 二.报错因素 1.提交.xlsx文件 2.提交时,.xlsx文件被 ...