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 ...
随机推荐
- Profinet网络的RT/IRT容量
轴数很多的时候,还考虑过PROFINET最大IRT容量的问题. [1]每个Profinet网络的RT个数, simition D 64 CPU 1511/1513-1 128 CPU 1515-2/1 ...
- git 和 github的学习
第一部分:我的github地址 https://github.com/Ly1235/gitLeaming 第二部分:git 和 github Git是一款免费.开源的分布式版本控制系统.gitHub是 ...
- select poll epoll相关知识速记
缘起 面试的时候经常被问的一个很蛋疼的问题,经常被问,但是知识很零散,难记忆,看完就忘 select 作用 可以监视文件描述符是否可以读写,要求监视的文件描述符是非阻塞的 诞生背景 产生与上个世纪80 ...
- bzoj3816 矩阵变换
Description 给出一个 N 行 M 列的矩阵A, 保证满足以下性质: M>N. 矩阵中每个数都是 [0,N] 中的自然数. 每行中, [1,N] 中每个自然数都恰好出现一次.这意味着每 ...
- SSH 本地和服务器传输
[转]https://www.cnblogs.com/magicc/p/6490566.html SCP 使用方式如下: 1.上传本地文件到服务器 scp /path/filename usernam ...
- 【[JLOI2014]松鼠的新家】
//第一次A掉紫题就来写题解,我是不是疯了 //说实话这道题还是比较裸的树上差分 //对于树上的一条路径(s,t),我们只需要把ch[s]++,ch[t]++,ch[LCA(S,T)]--,再把lca ...
- U3
一个项目里面可以有多个Activity AndroidManifest.xml<intent-filter> <action android:name="android.i ...
- [18/12/03] 多态(polymorphism)和对象的转型(casting)
一.多态 多态指的是同一个方法调用,由于对象不同可能会有不同的行为.现实生活中,同一个方法,具体实现会完全不同. 比如:同样是调用人的“休息”方法,张三是睡觉,李四是旅游,同样是调用人“吃饭”的方法, ...
- 学大伟业 Day 4 培训总结
今天讲的全是dp... 不多废话,先看一道经典的模板LIS(最长不下降子序列) 一.LIS 给定一个长度为N的数列,求最长上升子序列 例:1 7 2 8 3 4 答案:1 2 3 4 代码: #inc ...
- scala容器使用
花了两个小时左右,学习了一下scala语言, 由于scala运行在jvm之上, 可以使用java容器也可以使用scala自带的容器. import java.util import java.util ...