首先来学学精确字符串匹配:
那我们要怎么找呢?:
好麻烦,有没有别的?:
指纹就是一个标识符,但这个标识符怎么找呢?
就是把每个字母当成一位十进制数的数字,我开头记录下目标的字符串是什么数字,然后再一个一个向前比较,数字相同就找到了。这和上面的暴力搜索一样也是一个一个向前找,但这个在比较m个字符串的时候复杂度大大降低了,总是只要改变2位,m再大也不怕。
但这个方法显然存在缺点。我要把一个字符串变成一个数,假如这个字符串很大,那这个数字就要大的受不了。我们来学习新的方法:
同一个数mod 了右mod,结果是一样的,所以这个公式是正确的。
现在介绍的方法都有一个问题,那就是每次比较都没有使用之前的知识,每次都重新比较。我想让每个字符都只匹配一次:
简单来讲,PI[q]的计算方法就是:计算我们要找的字符串P中前q个字符中,前缀等于后缀的最大部分。例如:
这样,我们在实际寻找这个字符串的时候,假如遇到了“有一部分相等”的情况,我们可以根据之前相等的部分直接跳过中间部分,利用了之前的记忆。
就比如开头的那一步,我发现头5个相等,第6个不等,我看一看我的PI[]数组,发现PI[5]=3,也就是说头三个和后三个是一样的,所以我们直接跳到后三个,这样就可以快很多了。
现在我们来看看逆方法:
就是反过来的暴力算法。
简单来说就是:我比较了一下P和我们目前搜索的部分,发现不一样,那我就看一下我搜索的部分的最后那个字符,看一下:我的P要往前走几位才能遇到和这一位相等的?移动的位数就是shift[字符]的大小。例如我发现最后一个字符是e,那我要往前走4位才能遇到下一个e,所以shift[e]=4.假如最后哪一位压根就不在P里,那当然就直接是移动m位欲避之而不及。
最后这两种方法都运用了“记忆”。