码迷,mamicode.com
首页 > 其他好文 > 详细

哈希与KMP

时间:2021-01-08 11:26:36      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:存储   seek   假设   pow   转换   位置   变量   实现   signed   

哈希算法与 \(KMP\) 算法是两种处理字符串问题的常用算法

哈希 \(Hash\)

哈希算法是通过构造一个哈希函数,将一种数据转化为可用变量表示或者是可作数组下标的数

哈希函数转化得到的数值称之为哈希值

通过哈希算法可以实现快速匹配与查找

字符串 \(Hash\)

一般用于寻找一个字符串的匹配串出现的位置或次数

对于哈希函数的构造,通常选取两个数互质的 \(Base\)\(Mod\) \((Base<Mod)\),假设字符串 \(S=s_1s_2s_3……s_n\)

则我们可以定义哈希函数 \(Hash(i)=(c_1\times Base^{i-1} +c_2\times Base^{i-2}+……+c_i\times Base^{0}) \mod Mod\) 来处理前 \(i\) 个字符的哈希值

然后对于 \(Base\) 的次方我们也可以将它存储到一个数组 \(Get[]\) 中,使得 \(Get[i]=Base^{i}\)

\(Tips:\) 使用 unsigned long long 通过它的自然溢出,可以省去哈希函数中取模的一步

以上步骤的代码实现比较容易,如下:

Get[0]=1;
for(int i=1;i<=m;i++) Get[i]=Get[i-1]*base; 
for(int i=1;i<=m;i++) val[i]=val[i-1]*b+(uLL)s1[i];

哈希表

一种高效的数据结构,对于查找的效率几乎等同于常数时间,同时容易实现

多产生的代价仅仅是消耗较多的内存,相当于用空间换取时间

对于哈希函数的构造,可以选择多种方法,比如除余法,乘积法,基数转换法等

为了减小不同的字符串出现相同的哈希值这种误差,可以选择较大的模数,也可以构造多个哈希函数,比较当所有哈希值相同时才判定两个字符串相同

\(STL\) 库中的 \(unordered_map\) 内部就相当于一个哈希表,其存储信息为无序的 \(pair\) 类型,对于不存在的键值赋值时会插入,而已存在的则不会改变,这里不多赘述

\[\]

\(KMP\) 算法

这个名字是由发明它的三位学者的名字集合而成的我忘了叫什么了

用来处理字符串匹配问题

通过处理出一个存储下一次从头匹配位置的数组,减少无用匹配的次数,从而优化时间复杂度

具体原理,就是匹配串从第一个字符开始与主串的字符匹配,每匹配一位主串的指针向后移一位,若字符相同则匹配串指针也向后移一位,否则匹配串的指针回到上一个相同字符的位置

没时间了,引例先咕一天

代码实现

Nxt[1]=0;Fir=0;
for(int i=1;i<m;i++){
    while(Fir>0&&s2[Fir+1]!=s2[i+1]) Fir=Nxt[Fir];
	if(s2[Fir+1]==s2[i+1]) ++Fir;
	Nxt[i+1]=Fir;
}//处理 Nxt 数组

Fir=0;
for(int i=0;i<n;i++){
    while(Fir>0&&s2[Fir+1]!=s1[i+1]) Fir=Nxt[Fir];
        if(s2[Fir+1]==s1[i+1]) ++Fir;
   	if(Fir==m){ans++;Fir=Nxt[Fir];}
}//统计匹配个数

可以看到预处理 \(Nxt\) 和主程序很像,因为预处理其实也是一个匹配串自我匹配的过程

例题

Power Strings
Seek the Name, Seek the Fame
OKR-Periods of Words
A Horrible Poem

哈希与KMP

标签:存储   seek   假设   pow   转换   位置   变量   实现   signed   

原文地址:https://www.cnblogs.com/KnightL/p/14243674.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!