對string進行hash算法


對string進行hash算法:

https://blog.csdn.net/Mikchy/article/details/103995537

實質上就是對每個字符串找到唯一相對應的數字值。

假設字符串為s,則對應映射值idx(s[i])=s[i]-'a'+1** (這里a對應1)

整個字符串所有字串的哈希表:

img

(類似十進制的表示,14,一開始是 0,然后 0 * 10 + 1 = 1,接着 1*10 + 4 = 14)。

base是人為設定進制,隨意>26,為降低沖突風險取133等數。

img

進行一系列優化之后得到比較好的公式:

img

例題1,自動溢出(不做取模運算)上面式子第一個內括號里的就是

實際使用上因為l-1可能為負數,所以進行加一處理類似這個樣子:最好把r,l從一開始計數以免混亂

ull hash1 = hash[y1+1] - hash[x1] * p[y1 + 1 - x1];
#define ull unsigned long long   // 自然溢出用 unsigned long long

class Solution {
public:
 
    int distinctEchoSubstrings(string text) {
    int num;// 子串滿足條件的個數
    int l ,r=0;
    int n=text.size();
    ull hash[n+1];
    hash[0]=0;
    ull base=29;
    ull p[text.length()];
    p[0]=1;
    unordered_set<ull> H;
    
    for(int j=1;j<text.length();j++){
        p[j]=p[j-1]*base;
        
    }
    //首先轉換整個字符串的哈希表,子串可以用主串的哈希表公式計算
    for(int i=0;i<text.length();i++){
        hash[i+1]=hash[i]*base+text[i]-'a'+1;
    }//哈希表的大小要超過字符串一個,因為第一個下標0無用

    //遍歷所有字串
    for(l=0;l<text.length();l++){
        for(r=l+1;r<text.length();r++){
            //求此時[l,r]串分開兩半的哈希值
            //子串長度只有偶數可以
            if((l-r)%2!=0){
                //分為[l,(r+l)/2]和[(r+l)/2+1,r]兩部分並比較其哈希值
                int x1,y1,x2,y2;
                x1=l;
                x2=(r+l)/2+1;
                y1=(r+l)/2;
                y2=r;
                ull hash1 = hash[y1+1] - hash[x1] * p[y1 + 1 - x1];
                ull hash2 = hash[y2+1] - hash[x2] * p[y2 + 1 - x2];
                if(hash1==hash2){
                    H.insert(hash1);
                }
            }
        }
    }

    num=H.size();
   // cout<<num<<endl;
    return num;
    }
};

這道題我遍歷子串的方式有點蠢,采用雙偽指針的方式,看別人是用長度和坐標表示


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM