HASH算法小结
一、简述
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算法小结的更多相关文章
- 一致性hash算法小结
把服务器的IP或者主机名作为key对2^32求余,余数一定是2^32-1,然后放到(平行映射)0~2^32次方首尾相连的环上. 理想状态下服务器会均匀分布在这个环上,当数据存储时,依然把key对2 ...
- 一致性 hash 算法( consistent hashing )a
一致性 hash 算法( consistent hashing ) 张亮 consistent hashing 算法早在 1997 年就在论文 Consistent hashing and rando ...
- 一致性 hash 算法
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- 一致性 hash 算法( consistent hashing )
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在cache 系统中应用越来越广泛: 1 基 ...
- [图论]Floyd 算法小结
Floyd 算法小结 By Wine93 2013.11 1. Floyd算法简介 Floyd算法利用动态规划思想可以求出任意2点间的最短路径,时间复杂度为O(n^3),对于稠密图, 效率要高于执行 ...
- 【转】一致性hash算法(consistent hashing)
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- 一致性hash算法 - consistent hashing
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- 怎样的 Hash 算法能对抗硬件破解
前言 用过暴力破解工具 hashcat 的都知道,这款软件的强大之处在于它能充分利用 GPU 计算,比起 CPU 要快很多.所以在破解诸如 WiFi 握手包.数据库中的口令 Hash 值时,能大幅提高 ...
- [转]一致性hash算法 - consistent hashing
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
随机推荐
- HCNA实验OSPF基础
1.拓扑图 方法: 1.配置接口IP 2.配置OSPF协议: [R2]ospf 100 [R2-ospf-100]area 0 [R2-ospf-100-area-0.0.0.0]network 12 ...
- Linux--Bind服务搭建
Bind域名解析服务 服务功能:提供域名解析 构建主从域名服务器 1)环境部署 ip=192.168.1.50(主) ip=192.168.1.51(从) [root@localhost Packag ...
- JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍
概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...
- 利用raphael画图
raphael是一个js的矢量库,可以js操作DOM可以实现柱形图.走势图等一些基本的图形: 一.使用: 在html中设置<div class="my"></di ...
- Python3条件控制语句
Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. if语句 if 条件: 代码块 elif 条件: 代码块 else: 代码块 python中用elif ...
- OO思想举例,控制翻转,依赖注入
(转自kumaws,原帖地址:http://www.cnblogs.com/kumaws/archive/2009/04/06/from_interface_to_DependencyInjectio ...
- 如何在Chrome development tool里查看C4C前台发送的请求细节
我们可以在Chrome development tool的network tab里观察到从前台UI发送到后台的HTTP请求: 更多Chrome Development Tool的使用工具请查看我的博客 ...
- Uva 12298 超级扑克2
题目链接:https://vjudge.net/problem/UVA-12298 题意: 1.超级扑克,每种花色有无数张牌,但是,这些牌都是合数:比如黑桃:4,6,8,9,10,,,, 2.现在拿走 ...
- NEUACM1132: Renew MST Quickly 增量最小生成树
题目链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1132 和UVa11354很类似 题意: 原先有一棵树,每次加一条边,看最小生成树大小: 这个和增量 ...
- 【转】Android应用程序窗口(Activity)窗口对象(Window)创建指南
在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...