參考資料
hash演算法模板以及簡單的入門題總結
【演算法學習】字串hash入門
字串hash在某些情況下要比map好用,因為在對字串進行預處理後可以o(1)時間查詢任意子串的雜湊值。
貌似現在出題人都會卡自然溢位(與base的選取無關),用雙hash或自己搞兩個模數可能會保險些,,,
模板
//-----自然溢位-----//
const ull base =
13331
;ull p[maxn]
;void
init()
struct myhash
void
init
(const
char str)
ull get_hash
(int i,
int length)
//從下標i開始長度為length的字串的hash值};
//--------hash二維矩陣---------//
//二維hash 取兩個base
//統計b矩陣在a矩陣中的出現次數
const ull base1 =
13331
;const ull base2 =
23333
;ull p1[maxn]
,p2[maxn]
;void
pre(
)int t,n1,m1,n2,m2;
char a[maxn]
[maxn]
,b[maxn]
[maxn]
;ull h[maxn]
[maxn]
;void
init()
ull get_hash
(int x,
int y,
int lx,
int ly)
intwork()
return0;
}//-----雙hash-----//
const ull mod1 =
402653189
;const ull mod2 =
805306457
;const ull base1 =
13331
;const ull base2 =
23333
;//備用 模數&base
//const ull mod1 = 1610612741;
//const ull mod2 = 1222827239;
//const ull base1 = 1331;
//const ull base2 = 131;
ull p[maxn][2
];void
init()
struct myhash
upr get_hash
(int pos,
int length);}
};upr make_hash
(char s)
return ans;
}
參考資料一裡面的題就不放這裡了,,,貼幾個學長部落格沒有的題(camp上講字串hash的例題)
1.bzoj3555 [ctsc2014]企鵝qq
題意:當兩個字串長度相等且僅有乙個位置上的字元不同時我們說這兩個字串相似,給定n個長度為l且互不相同的字串,求有多少對字串是相似的。
題解:先對每乙個字串預處理出字首雜湊值和字尾雜湊值,這樣就可以在o(1)的時間內查詢字串去掉某乙個字元後的雜湊值,列舉字串去掉的是哪一位,將所有字串去掉這一位後的雜湊值丟到一起排下序,o(n)統計答案即可,總時間複雜度o(l
(nlo
gn+2
n)
)o(l(nlogn+2n))
o(l(nl
ogn+
2n))
。
const ull base =
13331
;ull p[n]
;vector<
char
> charset;
void
init()
inline
intindex
(char c)
struct myhash
ull sub_hash
(int i)};
int n,l,s;
char s[maxn]
;myhash h[maxn]
;vector a[n]
;ll ans=0;
intwork()
}return
printf
("%lld\n"
,ans)
;}
2.bzoj 2084[poi2010]antisymmetry
題意:對於乙個只包含01的字串,如果把它按位取反後翻轉的結果和原字串是一樣的,我們稱這個字串是反對稱的,求給定01串中反對稱子串的個數。
題解:manacher模板題 首先反對稱串的長度一定偶數,而且如果子串[l,
r]
[l,r]
[l,r
]是反對稱串的話, [l−
1,r−
1]
[l-1,r-1]
[l−1,r
−1]也一定是反對稱串,所以我們可以列舉對稱點並二分答案計算以這個點為對稱點的反對稱串的長度,記得預處理出原串取反並翻轉後的雜湊值,這樣就可以在二分答案時o(1
)o(1)
o(1)
判斷了,總時間複雜度o(n
logn
)o(nlogn)
o(nlog
n)。
const ull base =
13331
;ull p[n]
;void
init()
inline
intindex
(char c)
struct myhash
ull get_hash
(int i,
int l)};
int n;
ll cnt=0;
char s1[maxn]
,s2[maxn]
;myhash hash1,hash2;
bool check
(int i,
int l)
intwork()
cnt+
=ans;
}return
printf
("%lld\n"
,cnt)
;}
3.bzoj1014 [jsoi2008]火星人prefix
題意:詢問字串兩個字尾的最長公共字首,要求支援插入,修改操作。
題解:splay維護序列的hash值,二分答案求最長公共字首。
乙個splay調一下午
感覺我寫的splay自帶大常數,,,10s時限9.988s跑過,,,
const ull base =
1331
;ull p[n]
;void
init_hash()
namespace splay
void
pushup
(int x)
void
build
(int
&x,int l,
int r,
int f,
char a)
void
init
(char a,
int n)
inline bool chk
(int x)
void
rotate
(int x)
void
splay
(int x,
int goal=0)
if(!goal) root=x;
}int
find
(int k,
int x=root)
return x;
}void
insert
(int pos,
char c)
ull get_hash
(int l,
int r)
void
change
(int pos,
char c)
void
print
(int x)
void
debug()
}int n,m;
char s[maxn]
;int
work()
printf
("%d\n"
,ans);}
}return0;
}
字串雜湊
參照演算法筆記p109,甲級1039 先假設字串均由大寫字母a z構成。在這個基礎上,不妨把a z視為0 25,這樣就把26個大寫字母對應到了26進製中。接著,按照將26進製轉化為10進製的思路,由進製的轉換結論可知,在進製轉換過程中,得到的10進製肯定是唯一的,由此便可實現將字串對映為整數的需求 ...
字串雜湊
昨天做了一道字串雜湊的題,感覺還好理解。今天的題看了 不知道為什麼,搜來搜去發現不知道的東西還很多,網上找到的東西也都是很零散,書上也沒有系統的講解。先自己整理一下這些零散的知識 關於字串涉及到的演算法大概有 hash kmp trie ac自動機等等,現在還都不明白是怎麼回事,這次先研究字串has...
字串雜湊
給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數l1,r1,l2,r2,請你判斷 l1,r1 和 l2,r2 這兩個區間所包含的字串子串是否完全相同。字串中只包含大小寫英文本母和數字。輸入格式 第一行包含整數n和m,表示字串長度和詢問次數。第二行包含乙個長度為n的字串,字串中只包含大小寫...