哈希處理字符串

  1. 什麼是哈希
    首先簡單說明一下什麼是哈希。平時可能已經聽到過哈希函數,而哈希更常用在通信中,哈希的原理就是通過對信息進行不可逆向的處理,並且如果兩個信息哪怕只有一個位信息的不同,那的到的最終值也是截然不同的兩個答案。由於不可逆向性,所以只能從原信息的到哈希值,而不能從哈希值的到原信息,所以對於連個信息,我們只要比較他們的哈希值是否相等那麼就可以判斷這兩個信息是否相同。
    哈希處理字符串也是這個道理。這裏我們要清楚的是,哈希值必定是通過原信息計算(存在取模)得到的簡化值,因此就必要存在着不同的信息的到的哈希值也是一樣的,但是我們只要做到把發生這種情況的概率降到很低,就可以滿足大部分要求了。

  2. 字符串的哈希
    字符串的哈希,查找字符串t在s中的位置,既把長度n=t.length()的字符串t哈希值求出來,然後再在s中從每個位置起始長度爲n的哈希值存出來,把哈希值比較一下,即可判斷字符串是否相等

    下面就是講解具體如何哈希,時間複雜度O(n+m)

    • 由於s中每個位置哈希值也是爲n,爲了避免t×s的時間複雜度,這裏中滾動哈希的方法
      H( C )=(c1bm1c_1b^{m-1}+c2bm2+...+cmb0c_2b^{m-2}+...+c_mb^0)mod h.根據這個公式我們就可以的出遞推方程
      H( C ) = H( C-1 )*B + cmc_m - c0bmc_{0}b^m
    • 哈希的數值直接用無符號的long long類型,h取264通過自然溢出進行取模運算
    • 哈希的基數b我們一般取1e8+7或者1e9+7,自己可一根據實際情況自己設定
  3. 代碼實現

     unsigned long long B = 1e8+7;
     //判斷字符串t是否在s中
     bool hash(string t,string s){
     	int l1=t.length(),l2=s.length();
     	if(t>s)return false;
     	
     	unsigned long long ull=1;
     	for(int i=0;i<l1;i++)ull*=B;
     	
     	unsigned long long a=0,b=0;
     	for(int i=0;i<l1;i++)a=a*B+t[i];
     	for(int i=0;i<l1;i++)b=b*B+s[i];
     	
     	for(int i=0;i+l1<=l2;i++){
     		if(a==b)return true;
     		if(i+l1<l2)
     		b=b*B+s[i+l1]-ull*s[i];
     	}
     	return false;
     }
    
  4. 對於S的最大後綴和t的最大前綴相等的最大長度問題

    對於這個問題我們依然可以通過哈希計算得到,想在哈希比較的值變爲t從前向後依次計算,s爲從後向前依次計算,而沒計算一個值,就進行比較一次,取最大的那個答案。代碼如下:

      unsigned long long B = 1e8+7;
      int overlap(string t,string s){
     	int l1=t.length(),l2=s.length();
     	unsigned long long a=0,b=0,t=1;
     	for(int i=1;i<=min(l1,l2);i++){
     		a=a+s[l2-i]*t;//計算a後綴的哈希值
     		b=b*B+t[i-1];//計算t前綴的哈希值
     		if(a==b)ans=i;
     		t*=B;
     	}
     	return ans;
     }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章