国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

算法---哈希及其在字符串中的應(yīng)用(字符串hash)

這篇具有很好參考價值的文章主要介紹了算法---哈希及其在字符串中的應(yīng)用(字符串hash)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

哈希算法

---前言

?????????"加密是信息時代的鎖,密碼是鑰匙。" - 斯科特·萊普斯基(Scott Adams)

? ? ? ? 當(dāng)今,為了信息的存儲安全,密碼學(xué)興起,哈希(hash)算法也由此應(yīng)運而生,哈希算法是一種加密算法,是將一個數(shù)據(jù)轉(zhuǎn)換為一個標(biāo)志,這個標(biāo)志和源數(shù)據(jù)有十分緊密的關(guān)系。哈希 算法還有一個特點,就是很難找到逆向的規(guī)律。所以在日常的使用中,哈希算法常被用來對字符串進行壓縮編碼,將一段字符串轉(zhuǎn)化成對應(yīng)的數(shù)字或其他標(biāo)志,以方便存儲和比較。

---正文

? ? ? ? ·整數(shù)哈希(哈希介紹)

? ? ? ? 做為競賽算法來說,整數(shù)哈希算法經(jīng)常用來存儲極大的數(shù)據(jù)以起到縮小數(shù)據(jù)規(guī)模的效果,而經(jīng)過哈希算法處理后的數(shù)據(jù)會被存到一個數(shù)據(jù)結(jié)構(gòu)-散列表(hash表)中,其采用映射的思想,可以通過關(guān)鍵字在表中快速查找數(shù)據(jù),而Hash函數(shù)的設(shè)計也層出不窮,在算法競賽中,最常用的就是取模法,下文也以取模法為例來介紹+實現(xiàn)。

舉個例子,對于數(shù)據(jù)5,9,18,28,16來說,如果使用hash表存儲,模數(shù)為7,那么就應(yīng)該為

5:5 mod 7=5,存儲在下標(biāo)為5處。

9:9 mod 7=2,存儲在下標(biāo)為2處。

18:18 mod 7=4,存儲在下標(biāo)為4處。

28:28 mod 7=0,存儲在下標(biāo)為0處。

16: 16 mod 7=2,應(yīng)當(dāng)存儲在下標(biāo)為2處。

算法---哈希及其在字符串中的應(yīng)用(字符串hash),算法,字符串,哈希,算法,哈希算法

????????這時我們發(fā)現(xiàn)16和9的模數(shù)相同,也就是說,發(fā)生了哈希沖突,對于整數(shù)哈希沖突,也有許多不同的解決方案,此處,提供兩種解決方案,開放地址法鏈地址法。

開放地址法:將當(dāng)前的數(shù)向后(或向其他方向,不定)挪移,直到可以存儲。

鏈地址法:將當(dāng)前的數(shù)在該下標(biāo)下再拉一條鏈,形成一個鏈表,并將該數(shù)存儲到鏈表下。

? ? ? ? 但是顯而易見,這兩種辦法對于解決哈希沖突并不十分有效,所以我們要盡量減少哈希沖突的情況,一般而言,將模數(shù)設(shè)為足夠大的質(zhì)數(shù)可以有效減少哈希沖突出現(xiàn)的情況。

? ? ? ? 不過,對于整數(shù)哈希,我們一般不需要手寫哈希,可以使用C++的STL庫中的自帶的無序map:unordered_map和無序集合:unordered_set來代替手寫整數(shù)哈希,故此處不附代碼,若想手寫直接按照上述過程模擬即可。

? ? ? ? ·字符串哈希(哈希拓展)

? ? ? ? 經(jīng)過上述介紹,我們知道利用哈希函數(shù)可以很快的查詢和比較,而對于字符串來說,若要比較字符串是否相等,需要逐位比較,效率顯然很低,時間復(fù)雜度為O(n),所以我們考慮使用哈希優(yōu)化,而如何將字符串轉(zhuǎn)成可以正常按位置比較大小的數(shù)字呢?,類比進制轉(zhuǎn)換,我們把字符串看成一個128進制(ASCII碼)的數(shù)字,每個字符相對應(yīng)的就是其ASCII碼值,再按權(quán)展開就能得到其哈希值,如abcd這個字符串,它的哈希值就是97*128^3+98*128^2+99*128^1+100*128^0,由此我們可以得到一個公式(其中hash[i]表示第1位到第i位的哈希值,base表示底數(shù),mod表示模數(shù),s是原字符串):

hash[i]=(hash[i-1]*base%mod+s[i]%mod)%mod

哈希值是可以進行正常比較的,我們類比十進制來理解,一個數(shù)按權(quán)展開后就是得到的原數(shù),其值完全可以正常比較,所以哈希值也是可以進行字符串之間的正常比較的,而且它不需要逐位比較,效率比逐位比較更高,基本為O(1),這樣就能極大程度的優(yōu)化時間,使得程序不會超時。

? ? ? ? 但是,一般來說,底數(shù)(即權(quán)值)最好要定義成一個質(zhì)數(shù)(避免哈希沖突),所以一般會選擇第一個比128大的質(zhì)數(shù)131來做底數(shù),不過,事實上,只要大小合理,且為質(zhì)數(shù),任何大于128的數(shù)都是一個不錯的底數(shù),但是最常用的底數(shù)仍然是131。

模板(求哈希值)

題面概括:

? ? ? ? 給定一個字符串,求其對應(yīng)的哈希值,對998244353取模。

思路:

? ? ? ??純模板題,直接按上述過程模擬即可。

代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-835351.html

#include<bits/stdc++.h>
using namespace std;
long long has[100005];
const int mod=998244353;
int main(){
    string s;
    getline(cin,s);
    has[0]=s[0]%mod;
    for(int i=1;i<s.size();i++){
    	has[i]=(has[i-1]*128+(long long)s[i]%mod)%mod;
	}
	cout<<has[s.size()-1];
    return 0;
}

T2.查字典

題面概括:

? ? ? ? 給定n組單詞和其翻譯后的單詞,然后輸入q個單詞,將單詞翻譯后輸出,如果沒有對應(yīng)的單詞則輸出“eh"。

思路:

? ? ? ??這道題也是模板題,先把原單詞轉(zhuǎn)為哈希值后存儲,每輸入一個需要翻譯的單詞,就將其的哈希值求出,并與之前求出的所有原單詞的哈希值做比較,如果相等,輸出記錄的對應(yīng)的翻譯后的單詞即可,如果沒有相等的單詞則輸出”eh"。

代碼:

#include<iostream>
using namespace std;
long long has[1005];
const int mod=998244353;
string k[1005];
int main(){
    int n,q;
    string s;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>k[i]>>s;
        int len=s.size();
        for(int j=0;j<len;j++){
            if(j==len-1){
                has[i]=(has[i]+(long long)s[j])%mod;
            }
            has[i]=((has[i]+(long long)s[j])*128)%mod;
        }
    }
    cin>>q;
    for(int i=1;i<=q;i++){
        cin>>s;
        int sum=0;
        int len=s.size();
        for(int j=0;j<len;j++){
            if(j==len-1){
                sum=(sum+(long long)s[j])%mod;
            }
            sum=((sum+(long long)s[j])*128)%mod;
        }
        bool flag=0;
        for(int j=1;j<=n;j++){
            if(sum==has[j]){
                flag=1;
                cout<<k[j]<<endl;
            }
        }
        if(flag==0){
            cout<<"eh"<<endl;
        }
    }
    return 0;
}

T3.消失的密文

———————————————————————————————————————————

前置知識:

? ? ? ??對于一個已經(jīng)求得下標(biāo)從1開始所有長度哈希值的字符串來說,如何求它的子串呢?,我們考慮將哈希值當(dāng)成前綴和的形式來求得,那么如果要求l~r這段子串的哈希值,是用hash[r]-hash[l-1]嗎?答案是否定的,因為,hash[l-1]比hash[r]少乘了r-l+1個base(底數(shù)),導(dǎo)致指數(shù)無法對齊,所以我們就可以得到正確的公式(hash(l,r)表示l~r這段子串的哈希值,p[i]表示底數(shù)的i次方):

hash(l,r)=(hash[r]-(hash[l-1]*p[r-l+1])%mod+mod)%mod

———————————————————————————————————————————

題面概括:

? ? ? ? 給定一個密碼表S,S[i]表示第i個小寫字母解密后對應(yīng)的字母(下標(biāo)由1開始),然后給出一條密文K,密文的末尾缺失了一部分單詞,而完整密文的前半段是密文,后半段是解密后的”明文“,要求求出最短的完整的密文。

思路:

? ? ? ??這道題的難點,也是中心,就在于如何確定給出的密文中哪部分是密文,那部分是“明文”,也就是完整密文的中點位置,對于這道題來說,密文不是很長,所以可以使用枚舉的方法來枚舉中點,先用hash數(shù)組記錄哈希值,再枚舉中點k,取最前面n-k個字符的哈希值和k后面n-k個字符的哈希值(先將面n-k個字符轉(zhuǎn)為明文后)作比較,如果兩者相等就說明k是最小的中點,直接跳出循環(huán)并輸出前k個密文和后k個明文即可。

代碼:

#include<bits/stdc++.h>
using namespace std;
long long has[100005],p[100005],mhas[100005];
const int mod=998244353;
long long mid;
map<char,char> ma,pma;
int main(){
    int n;
    string s,b;
    cin>>n;
    for(int i=1;i<=n;i++){
    	ma.clear();
    	pma.clear();
        memset(has,0,sizeof has);
        memset(mhas,0,sizeof mhas);
        cin>>s>>b;
        b=' '+b;
        s=' '+s;
        for(int i=1;i<=s.size();i++){
        	ma['a'-1+i]=s[i];
        	pma[s[i]]='a'-1+i;
		}
        int len=b.size();
        len-=1;
        p[1]=1;
        for(int j=2;j<=len;j++){
            p[j]=p[j-1]*128;
        }
        for(int j=1;j<=len;j++){
            if(j==len){
                has[j]=has[j-1]+(long long)b[j];
                mhas[j]=mhas[j-1]+(long long)ma[b[j]];
            }
            has[j]=(has[j-1]+(long long)b[j])*128;
            mhas[j]=(mhas[j-1]+(long long)ma[b[j]])*128;
        }
        for(int j=(len+1)/2;j<=len;j++){
            long long hh=mhas[len]-mhas[j-1]*p[len-(j-1)+1];
            if(has[len-j+1]==hh){
                mid=j;
                break;
            }
        }
		for(int j=1;j<mid;j++){
			cout<<b[j];
		}
		for(int j=1;j<mid;j++){
			cout<<pma[b[j]];
		}
		cout<<"\n";
    }
    return 0;
}

T4.不同子串(雙哈希)

———————————————————————————————————————————

前置知識:

? ? ? ? 整數(shù)哈希中最重要的問題便是哈希沖突,而在字符串哈希中同樣如此,由于字符串哈希的局特殊性,我們無法使用一些在整數(shù)哈希中使用的方法來解決哈希沖突,所以我們主要來通過方法使得哈希沖突的概率降到一個極其微小的地步,這里介紹一個方法:雙哈希,顧名思義,就是對同一個字符串,使用兩個底數(shù)不同且模數(shù)不同的哈希函數(shù)分別求值,在判斷時要求兩個哈希函數(shù)的值必須都一一對應(yīng)才能判斷兩個字符串相等,這樣能令哈希沖突基本不可能出現(xiàn)。

———————————————————————————————————————————

?題面概括:

? ? ? ??給出一個字符串S,求這個字符串中有多少長度不同的子串。

思路:

? ? ? ? 這道題是一道經(jīng)典的哈希例題,但是如果直接使用單哈希會被卡數(shù)據(jù),所以考慮使用雙哈希,與上一題相同,這道題也是枚舉所有字串開頭的字符下標(biāo)位置(也可以是結(jié)尾字符下標(biāo)位置),然后對沒有出現(xiàn)的哈希值進行記錄,并累加,最后累加的值即為答案,輸出即可,注意,在記錄和判斷時要使用pair,否則會出現(xiàn)數(shù)據(jù)不對應(yīng)導(dǎo)致答案錯誤。

代碼:

//雙哈希 
#include<bits/stdc++.h>
using namespace std;
long long hasa[1000005],hasb[1000005],p[1000005],p1[1000005];
const int mod=1e9+7,modb=998244353;
const int base=131,base1=128;
map<pair<long long,long long>,int> ma;
int main(){
    string s;
	int n,l;
	cin>>n>>l;
	cin>>s;
	s=' '+s;
	int len=s.size();
	len-=1;
	p[0]=p1[0]=1;
	for(int i=1;i<=len;i++){
	    p[i]=p[i-1]*base%mod;
	    p1[i]=p1[i-1]*base1%modb;
	}
	for(int i=1;i<=len;i++){
	    hasa[i]=((hasa[i-1]*base)%mod+(long long)s[i]%mod)%mod;
	    hasb[i]=((hasb[i-1]*base1)%modb+(long long)s[i]%modb)%modb;
	}
	long long cnt=0;
	for(int i=l;i<=len;i++){
	    long long xx=hasa[i]-hasa[i-l]*p[l]%mod;
	    long long yy=hasb[i]-hasb[i-l]*p1[l]%modb;
	    //cout<<i<<":"<<xx<<" "<<yy<<endl; 
	    if(ma[make_pair(xx,yy)]==0){
	    	cnt++;
		}
		ma[make_pair(xx,yy)]=1;
	}
	cout<<cnt;
	return 0;
}

到了這里,關(guān)于算法---哈希及其在字符串中的應(yīng)用(字符串hash)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【JavaScript數(shù)據(jù)結(jié)構(gòu)與算法】字符串類(反轉(zhuǎn)字符串中的單詞)

    【JavaScript數(shù)據(jù)結(jié)構(gòu)與算法】字符串類(反轉(zhuǎn)字符串中的單詞)

    個人簡介 ?? 個人主頁: 前端雜貨鋪 ???♂? 學(xué)習(xí)方向: 主攻前端方向,也會涉及到服務(wù)端(Node.js) ?? 個人狀態(tài): 在校大學(xué)生一枚,已拿多個前端 offer(秋招) ?? 未來打算: 為中國的工業(yè)軟件事業(yè)效力 n 年 ?? 推薦學(xué)習(xí):??前端面試寶典 ??Vue2 ??Vue3 ??Vue2/3項目

    2023年04月09日
    瀏覽(25)
  • 前端算法題——字符串中的第一個唯一字符

    給定一個字符串,找到它的第一個不重復(fù)的字符,并返回它的索引。如果不存在,則返回 -1。 遍歷字符串 用一個對象來記數(shù),出現(xiàn)過一次就+1, 遍歷完畢,再次遍歷字符串,看它們在之前記錄的對象里的值,是否是1,是就返回下標(biāo),不是返回-1。

    2024年02月22日
    瀏覽(18)
  • Python 中的字符串基礎(chǔ)與應(yīng)用

    在Python中,字符串可以用單引號或雙引號括起來。\\\'hello\\\' 與 \\\"hello\\\" 是相同的。您可以使用print()函數(shù)顯示字符串文字: 示例: 將字符串分配給變量是通過變量名后跟等號和字符串完成的: 示例 您可以使用三個引號將多行字符串分配給變量:示例,您可以使用三個雙引號: 或

    2024年02月08日
    瀏覽(22)
  • 力扣熱門算法題 349. 兩個數(shù)組的交集,387. 字符串中的第一個唯一字符,394. 字符串解碼

    力扣熱門算法題 349. 兩個數(shù)組的交集,387. 字符串中的第一個唯一字符,394. 字符串解碼

    349. 兩個數(shù)組的交集,387. 字符串中的第一個唯一字符,394. 字符串解碼,每題做詳細(xì)思路梳理,配套PythonJava雙語代碼, 2024.04.02?可通過leetcode所有測試用例。 目錄 349. 兩個數(shù)組的交集 解題思路 完整代碼 Python Java 387. 字符串中的第一個唯一字符 解題思路 完整代碼 Python Java

    2024年04月08日
    瀏覽(31)
  • 算法:刪除字符串中的所有相鄰重復(fù)項

    提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 目錄 一、問題描述 二、棧解法 三、雙指針解法 總結(jié) 提示:以下是本篇文章正文內(nèi)容,下面案例可供參考 給出由小寫字母組成的字符串str,重復(fù)項刪除操作會選擇兩個相鄰且相同的字母,并刪除它們。

    2024年01月22日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu)與算法之字符串: Leetcode 557. 反轉(zhuǎn)字符串中的單詞 III (Typescript版)

    翻轉(zhuǎn)字符串中的單詞 III https://leetcode.cn/problems/reverse-words-in-a-string-iii/ 描述 給定一個字符串 s ,你需要反轉(zhuǎn)字符串中每個單詞的字符順序,同時仍保留空格和單詞的初始順序。 示例 1: 示例 2: 提示: 1 = s.length = 5 * 1 0 4 10^4 1 0 4 s 包含可打印的 ASCII 字符。 s 不包含任何開頭或

    2024年02月01日
    瀏覽(24)
  • 哈希表+字符串

    哈希表+字符串

    一)知識回顧: 1)哈希表是什么?哈希表是存儲數(shù)據(jù)的容器 2)哈希表有啥用?快速的查找某一個元素 3)什么時候使用哈希表?頻繁的查找某一個數(shù)的時候, 當(dāng)我們快速查找某一個數(shù)的時候,不光要想到哈希表還需要想到二分查找,但是二分查找算法的局限性太強了,必須數(shù)組中有序

    2024年02月10日
    瀏覽(18)
  • 2023-8-26 字符串哈希

    2023-8-26 字符串哈希

    題目鏈接:字符串哈希

    2024年02月11日
    瀏覽(20)
  • LeetCode 2744.最大字符串配對數(shù)目:哈希表

    力扣題目鏈接:https://leetcode.cn/problems/find-maximum-number-of-string-pairs/ 給你一個下標(biāo)從 0 ?開始的數(shù)組? words ?,數(shù)組中包含 互不相同 ?的字符串。 如果字符串? words[i] ?與字符串 words[j] ?滿足以下條件,我們稱它們可以匹配: 字符串? words[i] ?等于? words[j] ?的反轉(zhuǎn)字符串。 0

    2024年01月22日
    瀏覽(23)
  • LeetCode-763. 劃分字母區(qū)間【貪心 哈希表 雙指針 字符串】

    給你一個字符串 s 。我們要把這個字符串劃分為盡可能多的片段,同一字母最多出現(xiàn)在一個片段中。 注意,劃分結(jié)果需要滿足:將所有劃分結(jié)果按順序連接,得到的字符串仍然是 s 。 返回一個表示每個字符串片段的長度的列表。 示例 1: 輸入:s = “ababcbacadefegdehijhklij” 輸

    2024年04月10日
    瀏覽(97)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包