字符串哈希及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 ... 
随机推荐
- Ubuntu: 软件库(software repositories)
			Linux 生态下,几乎每个发行版都有自己的软件库(software repositories),Ubuntu 当然也不例外.Ubuntu 提供了四个不同的软件库,分别是 main.restricte ... 
- Bean笔记
			为什么需要Bean , 因为 Aop 需要. 顺序 InstantiationAwareBeanPostProcessor , BeanPostProcessor 每个Bean都会执行这两个组件的相关 ... 
- PySpider框架的基本用法
			pyspider安装: 3.7之后无法正常使用,使用可以下载Python3.6或以下,或者修改pyspider内部代码 ———————————————————————————————————————— ... 
- Python是如何进行内存管理
			三个方面:一对象的引用计数机制,二垃圾回收机制,三内存池机制 一.对象的引用计数机制 Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数. 引用计数增加的情况: 1,一个对象分 ... 
- 学习memcache
			本文参考了菜鸟教程中的内容. 安装 安装memcache的时候,请切换为root用户 root@centos # wget http://www.memcached.org/files/memcach ... 
- Problem 2285 迷宫寻宝
			http://acm.fzu.edu.cn/problem.php?pid=2285 Problem Description 洪尼玛今天准备去寻宝,在一个n*n (n行, n列)的迷宫中,存在着一个入 ... 
- React Native之code-push的热更新(ios android)
			React Native之code-push的热更新(ios android) React Native支持大家用React Native技术开发APP,并打包生成一个APP.在动态更新方面React ... 
- tomcat8.0部署启动
			http://tomcat.apache.org/download-80.cgi 打开命令行提示符窗口, 进入Tomcat安装目录, 进入bin目录下, 输入:service.bat install ... 
- Oracle创建'数据库'三步走
			--创建表空间 create tablespace waterboss datafile 'd:\waterboss.dbf' size 100m autoextend on next 10m; -- ... 
- java中级——二叉树比较冒泡和选择排序
			上次我们说到二叉树排序比较,给出如下的题目 题目:创建五万个随机数,然后用分别用冒泡法,选择法,二叉树3种排序算法进行排序,比较哪种更快 废话不说直接上源码,可以看控制台结果 注意的是 需要我们需要上 ... 
