字符串哈希及KMP
字符串很神奇,因为它在计算机中应用很广泛,就每一个程序都需要用到字符串,所以学好字符串是非常重要的。
接下来就介绍两个字符串的基本操作
1:字符串hash 一种可以查找几个字符串有几个不同的字符串。
其精髓就是把一堆字符串都转换成几个数字的和的形式。
要领就是把字符串每一位字母的阿斯克码不会拼啊都乘上一个比较神奇的数,再%上一个神奇的数,比如你的生日啊,qq号什么的,尽量是质数,太大了也不行,会爆炸的。
van成之后,再把这个值都存进一个数组中,最后查的时候直接用就是了。
为什么这样就可以实现查找不同的字符串呢。
因为这相当于给每个字符串一个编号,且这个编号就是每个字符串的每个位数乘上一个上文提到的很神奇的数,来保证不会出现编号重了的现象。
如果这样你还是觉得不保险,你还可以双hash,这样成功率会大大增加,但还是不排除出现错误,这种情况又叫哈希冲突。
好了,解释完毕上代码
#include<iostream>
#include<string>
#include<cstdio>
#include<map>
using namespace std;
const int mod=;
int n,hash[],total;
map<int,int>m;
string s;
int find_hash(string x)
{
int ans=;
for(int i=;i<x.size();i++)
{
ans=(ans*%mod+((int)x[i]))%mod;
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
cin>>s;
hash[i]=find_hash(s);
}
for(int i=;i<=n;i++)
{
if(m[hash[i]])continue;
m[hash[i]]=;
total++;
}
printf("%d",total);
}
2:KMP字符串匹配算法
既然知道了如何查找不同的算法,那么接下来就要实现KMP字符串匹配了,
KMP字符串匹配就是指 给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
当然就需要引进一个数组叫next数组也叫子串的前缀数组。
next数组指什么呢,指这个串的最长的前缀与后缀相等的长度。
比如说
下标:01234
值: ABABA
的next数组是
下标:01234
值: 00123
因为字符串的第一位的下标默认为0.
所以我们也把下标弄成和字符串一样的格式.
有了这个数组有什么用呢?
我们想如果这个字符串失配了,那这个位置的子串字符一定不与父串字符相等,但是之前的所有字符都相等。
所以我们就匹配到之前的相等的字符处
比如:
父串:ABABCABABA
子串: ABABA
当匹配到s1[4] 和 s2[4]时(以字符串的下标)s1[4]!=s2[4]
我们就要回到之前的位置,那之前的位置在哪呢,你可能会想应该在next[4]这里吧,但是你看如果在next[4]这里,那么s2[现在失配的位置]=s2[next[4]]那我们这样做有什么用呢照样失配,
所以我们应该回到next[i-1]的位置,或者让next的下标集体+1,这就是有些KMP的代码中有现在失配的位置=next[现在失配的位置]。
还有一点,第0位的next数组是算不出来的,所以我们找next数组的函数中的循环要从1开始。
但是如果父串的这个位置与任何的前缀都不行,那就只能放弃这个位置了,让父串的位置+1.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char a[1000010],b[1000010];
int n,m,j,next[1000010];
void pre()
{
next[1]=0;
j=0;
for(int i=1;i<m;i++)
{
while(j>0&&b[i]!=b[j])
j=next[j-1];
if(b[i]==b[j])
j++;
next[i]=j;//这一步在上一步的原因是,nex[i]是i失配后要跳到的不等于s[i-1]和s[i]的一个字符的位置,所以j要加1之后b[nex[i]]就不等于b[i]了
}
}
void kmp()
{
for(int i=0;i<n;i++)
{
while(j>0&&a[i]!=b[j])
j=next[j-1];
if(a[i]==b[j])
j++;
if(j==m)
{
cout<<i+1-(m-1)<<endl;//j要返回到上次的位置,这样可以使i重复利用,因此不能使j=0;
}
}
}
int main()
{
cin>>a;
cin>>b;
n=strlen(a);
m=strlen(b);
pre();
j=0;
kmp();
for(int i=0;i<m;i++)
cout<<next[i]<<" ";
}
字符串哈希及KMP的更多相关文章
- UVA - 11475 Extend to Palindrome —— 字符串哈希 or KMP or 后缀数组
题目链接:https://vjudge.net/problem/UVA-11475 题意: 给出一个字符串,问在该字符串后面至少添加几个字符,使得其成为回文串,并输出该回文串. 题解: 实际上是求该字 ...
- 【CodeForces】961 F. k-substrings 字符串哈希+二分
[题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} ...
- UVA - 11019 Matrix Matcher (二维字符串哈希)
给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数. 看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希. 类比一维情况下的哈希算法,利用容斥 ...
- Luogu P4503 [CTSC2014]企鹅QQ(字符串哈希)
P4503 [CTSC2014]企鹅QQ 题面 题目背景 \(PenguinQQ\) 是中国最大.最具影响力的 \(SNS(Social Networking Services)\) 网站,以实名制为 ...
- Petr#(字符串哈希)
CF113B Petr# 大概就是字符串匹配加一个字符串哈希判重.懒得打kmp,就用字符串哈希匹配了. 字符串哈希大概就是把字符串转成一个p进制的数,每一段字符串都有一个对应的哈希值.p尽量取质数,这 ...
- HDU 1880 魔咒词典(字符串哈希)
题目链接 Problem Description 哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一 ...
- 洛谷P3370 【模板】字符串哈希
P3370 [模板]字符串哈希 143通过 483提交 题目提供者HansBug 标签 难度普及- 提交 讨论 题解 最新讨论 看不出来,这题哪里是哈希了- 题目描述 如题,给定N个字符串(第i个 ...
- HDU2594 Simpsons’ Hidden Talents 字符串哈希
最近在学习字符串的知识,在字符串上我跟大一的时候是没什么区别的,所以恶补了很多基础的算法,今天补了一下字符串哈希,看的是大一新生的课件学的,以前觉得字符串哈希无非就是跟普通的哈希没什么区别,倒也没觉得 ...
- LA 6047 Perfect Matching 字符串哈希
一开始我用的Trie+计数,但是不是计多了就是计少了,后来暴力暴过去的…… 看了别人的代码知道是字符串哈希,但是仍有几个地方不理解: 1.26^500溢出问题 2.没考虑哈希碰撞? 跪求指点! #in ...
随机推荐
- H5 38-背景图片和插入图片区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- HDU - 1542 扫描线入门+线段树离散化
扫描线算法+线段树维护简介: 像这种求面积的并集的题目,就适合用扫描线算法解决,具体来说就是这样 类似这种给出点的矩形的对角的点的坐标,然后求出所有矩形面积的交集的问题,可以采用扫描线算法解决.图如下 ...
- BFC 原理
BFC:Block-level box + Forating + Context; ------->块元素 决定其子元素如何定位, ...
- transfer.sh:通过命令行简单的创建文件分享
简介 通过一个命令,就可以在终端上,将文件加密传输到远程服务器,提供对外文件共享的功能. transfer.sh这是一个我常用的.可以在终端上使用的文件共享服务,可以在某些方面替代sz或者scp命令. ...
- #Leetcode# 1009. Complement of Base 10 Integer
https://leetcode.com/problems/complement-of-base-10-integer/ Every non-negative integer N has a bina ...
- Druid Monitor开启登录界面
<!-- druid --> <filter> <filter-name>druidWebStatFilter</filter-name> <fi ...
- 微信开发 提示 Redirect_uri(错误10003)
情景: 搭建完成一个网站,使用微信打开链接地址,结果报错1003 完整的错误信息: 出现这种情况一般有两种原因: 1.没有配置网页授权 我们可以根据微信的开发者文档http://mp.weixin. ...
- LR 两种html与url录制
一直在使用LR,对于Html_based script和Url-based script 两种录制方式之间,要如何选择,仍是一知半解.最近测试时遇到同样的业务功能,两种录制方式的脚本,单次执行时间差别 ...
- zepto的extend
类型判断 var class2type = {},toString = class2type.toString,$={}; //判断类型 function type(obj) { return obj ...
- python之路--MySQl单表查询
一. 关键字的执行优先级(重点) from where group by having # 使用是要放在group by 后面而且前面必须有group by select distinct # 去重 ...