對string進行hash演算法
阿新 • • 發佈:2021-08-06
對string進行hash演算法:
https://blog.csdn.net/Mikchy/article/details/103995537
實質上就是對每個字串找到唯一相對應的數字值。
假設字串為s,則對應對映值idx(s[i])=s[i]-'a'+1** (這裡a對應1)
整個字串所有字串的雜湊表:
(類似十進位制的表示,14,一開始是 0,然後 0 * 10 + 1 = 1,接著 1*10 + 4 = 14)。
base是人為設定進位制,隨意>26,為降低衝突風險取133等數。
進行一系列優化之後得到比較好的公式:
例題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; } };
這道題我遍歷子串的方式有點蠢,採用雙偽指標的方式,看別人是用長度和座標表示