哈希处理字符串
-
什么是哈希
首先简单说明一下什么是哈希。平时可能已经听到过哈希函数,而哈希更常用在通信中,哈希的原理就是通过对信息进行不可逆向的处理,并且如果两个信息哪怕只有一个位信息的不同,那的到的最终值也是截然不同的两个答案。由于不可逆向性,所以只能从原信息的到哈希值,而不能从哈希值的到原信息,所以对于连个信息,我们只要比较他们的哈希值是否相等那么就可以判断这两个信息是否相同。
哈希处理字符串也是这个道理。这里我们要清楚的是,哈希值必定是通过原信息计算(存在取模)得到的简化值,因此就必要存在着不同的信息的到的哈希值也是一样的,但是我们只要做到把发生这种情况的概率降到很低,就可以满足大部分要求了。 -
字符串的哈希
字符串的哈希,查找字符串t在s中的位置,既把长度n=t.length()的字符串t哈希值求出来,然后再在s中从每个位置起始长度为n的哈希值存出来,把哈希值比较一下,即可判断字符串是否相等下面就是讲解具体如何哈希,时间复杂度O(n+m)
- 由于s中每个位置哈希值也是为n,为了避免t×s的时间复杂度,这里中滚动哈希的方法
H( C )=(+)mod h.根据这个公式我们就可以的出递推方程
H( C ) = H( C-1 )*B + - - 哈希的数值直接用无符号的long long类型,h取264通过自然溢出进行取模运算
- 哈希的基数b我们一般取1e8+7或者1e9+7,自己可一根据实际情况自己设定
- 由于s中每个位置哈希值也是为n,为了避免t×s的时间复杂度,这里中滚动哈希的方法
-
代码实现
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; }
-
对于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; }