ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

字符串学习笔记

2020-07-22 20:31:49  阅读:265  来源: 互联网

标签:匹配 bas ll 笔记 学习 哈希 KMP 字符串


一、字符串哈希

定义

字符串哈希实质上就是把每个不同的字符串转成不同的整数
这样相对于存储整个字符串来说占用的空间更少,而且也便于比较

实现

我们可以把每一个字符想象成一个数字,然后确立一个进制\(bas\)
比如一个字符串\(abc\)
我们可以把它表示为\((c-a+1)\times bas^{0} + (b-a+1)\times bas^{1} +(a-a+1)\times bas^{2}\)
这里有几个需要注意的地方
首先进制的选择要大于字符的种类数,否则会有很大的概率出现冲突
还有就是我们在把字符转成整形的时候,可以直接使用它的\(ASCII\)码值,也可以用它减去一个字符
但是在使用第二种方法的时候,减去一个字符后要加上一个\(1\),否则会出现错误
比如字符串\(aaa\)和\(aa\),如果我们将每一个字符减去\(a\)后不把它加上\(1\)的话
最后两个字符串的哈希值都会变成\(0\),也就是说会把这两个字符串判成相等,会出现错误的结果
由于字符串的长度可能很大,因此如果我们一直把它的哈希值累加的话,很有可能会溢出
因此,我们要对某个字符串的哈希值取模,方法有两种
一种是选取一个较大的质数
比如\(19260817\)、\(19660813\)、\(1222827239\)、\(212370440130137957\)
另一种是使用\(unsigned long long\)使其自然溢出
其实后一种方法就相当于对\(2^{64}-1\)取模
还有一种操作是取出字符串中某一段字符\([l,r]\)的\(hash\)值
这时我们要用到一个公式\(ha[r]-ha[l-l]*pw[r-l+1]\)
其中\(ha[i]\)为该字符串前\(i\)位的\(hash\)值,\(pw[i]\)为进制\(bas\)的\(i\)次方

代码实现

我们拿洛谷P3370来举例子
这里我用的是自然溢出

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int maxn=1e5+5;
ll f[maxn];
ll bas=233,cnt=0;
ll get_hash(char s[]){
    ll ans=0,len=strlen(s);
    for(ll i=0;i<len;i++){
        ans=ans*bas+s[i];
    }
    return ans;
}
char s[maxn];
int main(){
    int n;
    scanf("%d",&n);
    while(n--){
        scanf("%s",s);
        f[++cnt]=get_hash(s);
    }
    sort(f+1,f+1+cnt);
    int now=1;
    for(ll i=2;i<=cnt;i++){
        if(f[i]!=f[i-1]) now++;
    }
    printf("%d\n",now);
}

二、KMP字符串匹配

定义

\(KMP\)算法是一种改进的字符串匹配算法,由\(D.E.Knuth,J.H.Morris\)和\(V.R.Pratt\)提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称\(KMP\)算法)。\(KMP\)算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个\(next()\)函数实现,函数本身包含了模式串的局部匹配信息。\(KMP\)算法的时间复杂度\(O(m+n)\)
通俗的来说就是在需要匹配的那个串上给每个位置一个失配指针\(fail[j]\),表示在当前位置j失配的时候需要返回到\(fail[j]\)位置继续匹配,而这就是KMP算法优秀复杂度的核心。

实现

我们设\(fail[i]\)为第\(1\)-第\(i\)位中前缀与后缀相同的部分最长是多长。
这样,即可以理解为,若第\(i\)位失配了,则至少要往前跳多少步,才可能重新匹配得上。

标签:匹配,bas,ll,笔记,学习,哈希,KMP,字符串
来源: https://www.cnblogs.com/liuchanglc/p/13362938.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有