【笔记】震惊!世上最接地气的字符串浅谈(HASH+KMP)
震驚!世上最接地氣的字符串淺談(HASH+KMP)
筆者過于垃圾,肯定會(huì)有些錯(cuò)的地方,歡迎各位巨佬指正,感激不盡!
引用:LYD的藍(lán)書,一本通,DFC的講稿,網(wǎng)上各路巨佬
Luguo id: 章魚那個(gè)哥, uid : 87075
Hash
哈希算是除字符串的題,別的什么題用處最多的一種東西了。
干啥子用的:
怎么說呢,就像是給出一個(gè)字符串,我們把他化成一個(gè)數(shù)字。
這樣可以實(shí)現(xiàn)快速查詢兩個(gè)字符串是否相同,需要 \(O(N)\) 預(yù)處理。
咋的寫:
把這個(gè)字符串轉(zhuǎn)換成一個(gè)BASE進(jìn)制數(shù),并對(duì)一個(gè)模數(shù)取模,最好這個(gè)模數(shù)是一個(gè)大質(zhì)數(shù),這樣對(duì)哈希沖突的影響小一點(diǎn),當(dāng)然有些時(shí)候是合數(shù)反而更好。
代碼:
inline int Hash(char s[],int p){int sum=0;for(int i=0;i<(int)strlen(s);++i)sum=(sum*BASE+(int)s[i])%P;return sum%p;
} 小拓展:
雙哈希:
這不是對(duì)哈希值哈希,對(duì)哈希值哈希會(huì)造成更大程度的信息損失。
是對(duì)兩個(gè)BASE,兩個(gè)模數(shù)分別做哈希。
樹哈希:
這個(gè)分好多種,有對(duì)樹形哈希的,有對(duì)子樹哈希的。
來看一道NOIP原題:
NOIP-2018對(duì)稱二叉樹
發(fā)現(xiàn)這題其實(shí)就是這個(gè)節(jié)點(diǎn)的兩個(gè)子樹的左序遍歷(Lson,now,Rson)和右序遍歷(Rson,now,Lson)相同時(shí)就可以更新答案了,那么我們其實(shí)就是要對(duì)這棵樹的形狀哈希,那么就可以想到一種辦法:
左兒子,當(dāng)前點(diǎn),右兒子附加不同的BASE。
每次更新就可以按照左序右序更新,最后判斷按照左序更新的哈希值和按照右序的哈希值是否一樣就行了
一些應(yīng)用:
可以在 \(O(NlogN)\) 時(shí)間內(nèi)求出一個(gè)回文串,可以枚舉中心,二分長(zhǎng)度,哈希判斷值
可以字符串匹配
可以瞎搞(可以參考NOIP-2014解方程)
當(dāng)然還有后綴排序啥子的,但筆者不會(huì),然而也莫得用到。。。
KMP
干啥子用的:
\(O(N+M)\) 匹配文本串中模式串出現(xiàn)的次數(shù)和位置等。
怎么做:
引入nxt[i]表示模式串長(zhǎng)度為 \(i\) 時(shí)前后綴字符串相同的最長(zhǎng)字符。
紅色為已匹配成功的
那么接下來我們發(fā)現(xiàn)上面的已匹配的后兩個(gè)是和下面的后兩個(gè)是匹配的,那么我們不必把模式串指針移動(dòng)回首位,只需要移動(dòng)到nxt[失配字符的前一個(gè)],后文中,這個(gè)"失配字符的前一個(gè)"稱作len。
這樣每次失配就不會(huì)浪費(fèi)時(shí)間從頭匹配。
nxt可以自己匹配自己求出來。
代碼
#include<bits/stdc++.h>
using namespace std;int n,m,len;
const int N=1e6+5;
char a[N],b[N];
int nxt[N];int main(){int ans=0;scanf("%s%s",a+1,b+1);n=strlen(a+1);m=strlen(b+1);for(int i=2;i<=m;++i){while(len && b[len+1]!=b[i]) len=nxt[len];if(b[len+1]==b[i]) len++;nxt[i]=len;}len=0;for(int i=1;i<=n;++i){while(len && b[len+1]!=a[i]) len=nxt[len];if(b[len+1]==a[i]) len++;if(len==m)ans++,len=nxt[len];}printf("%d\n",ans);for(int i=1;i<=m;++i) printf("%d ",nxt[i]);putchar('\n');return 0;
} 小拓展:
好像莫得,nxt數(shù)組倒有些別的用處。
小應(yīng)用:
可以 \(O(N)\) 求最小循環(huán)節(jié)長(zhǎng)度。考慮如果循環(huán)節(jié)長(zhǎng)度為ans,
那么肯定會(huì)有 n-ans=nxt[n]
此篇完結(jié),撒花~~
下一篇——Trie樹和Manacher
轉(zhuǎn)載于:https://www.cnblogs.com/JCNL666/p/10810271.html
總結(jié)
以上是生活随笔為你收集整理的【笔记】震惊!世上最接地气的字符串浅谈(HASH+KMP)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zookeeper 和 dubbo 配置
- 下一篇: Python网络爬虫--urllib