字符串很神奇,因为它在计算机中应用很广泛,就每一个程序都需要用到字符串,所以学好字符串是非常重要的。

接下来就介绍两个字符串的基本操作

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的更多相关文章

  1. UVA - 11475 Extend to Palindrome —— 字符串哈希 or KMP or 后缀数组

    题目链接:https://vjudge.net/problem/UVA-11475 题意: 给出一个字符串,问在该字符串后面至少添加几个字符,使得其成为回文串,并输出该回文串. 题解: 实际上是求该字 ...

  2. 【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} ...

  3. UVA - 11019 Matrix Matcher (二维字符串哈希)

    给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数. 看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希. 类比一维情况下的哈希算法,利用容斥 ...

  4. Luogu P4503 [CTSC2014]企鹅QQ(字符串哈希)

    P4503 [CTSC2014]企鹅QQ 题面 题目背景 \(PenguinQQ\) 是中国最大.最具影响力的 \(SNS(Social Networking Services)\) 网站,以实名制为 ...

  5. Petr#(字符串哈希)

    CF113B Petr# 大概就是字符串匹配加一个字符串哈希判重.懒得打kmp,就用字符串哈希匹配了. 字符串哈希大概就是把字符串转成一个p进制的数,每一段字符串都有一个对应的哈希值.p尽量取质数,这 ...

  6. HDU 1880 魔咒词典(字符串哈希)

    题目链接 Problem Description 哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一 ...

  7. 洛谷P3370 【模板】字符串哈希

    P3370 [模板]字符串哈希 143通过 483提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 看不出来,这题哪里是哈希了- 题目描述 如题,给定N个字符串(第i个 ...

  8. HDU2594 Simpsons’ Hidden Talents 字符串哈希

    最近在学习字符串的知识,在字符串上我跟大一的时候是没什么区别的,所以恶补了很多基础的算法,今天补了一下字符串哈希,看的是大一新生的课件学的,以前觉得字符串哈希无非就是跟普通的哈希没什么区别,倒也没觉得 ...

  9. LA 6047 Perfect Matching 字符串哈希

    一开始我用的Trie+计数,但是不是计多了就是计少了,后来暴力暴过去的…… 看了别人的代码知道是字符串哈希,但是仍有几个地方不理解: 1.26^500溢出问题 2.没考虑哈希碰撞? 跪求指点! #in ...

随机推荐

  1. redis-trib.rb命令详解

    redis-trib.rb是官方提供的Redis Cluster的管理工具,无需额外下载,默认位于源码包的src目录下,但因该工具是用ruby开发的,所以需要准备相关的依赖环境. 准备redis-tr ...

  2. 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?

    注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...

  3. 页面添加iconfont字体-[超详细]-支持彩色

    第一步: 去矢量图官网注册一下,获取小图标(字体) 的来源 (也可以是其他类似的网站)这里以 阿里妈妈矢量图 官网为例,因为图标丰富,方便使用. 注册请点:https://www.iconfont.c ...

  4. H5 颜色属性

    07-颜色属性 我是段落 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  5. MySQL数据库性能优化思路与解决方法(二转)

    原文:http://bbs.landingbj.com/t-0-242512-1.html 1.锁定表 尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是 ...

  6. Laravel 服务容器、服务提供器、契约实例讲解

        前言 刚开始看laravel服务容器.契约.服务提供器的确生涩难懂,不单单是概念繁多,而且实际的demo很难找(找是找到了,但难用啊),最后就隔一段时间看一遍,大概个十来遍,还真给看出个门道, ...

  7. 并发包 concurrent(一) Atomic

    1:基础概念 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传 ...

  8. 用户认证--------------auth模块

    一.auth模块 from django.contrib import auth 1 .authenticate()   :验证用户输入的用户名和密码是否相同 提供了用户认证,即验证用户名以及密码是否 ...

  9. IntelliJ IDEA启动Tomcat后,却无法访问Tomcat主页 等一系列问题

    1.IntelliJ IDEA启动Tomcat后,却无法访问Tomcat主页 转:http://www.myexception.cn/other/1998827.html https://blog.c ...

  10. docker学习笔记二

    知识点: 1)手动构建镜像 2)Dockerfile快速构建镜像 阿里云yum源https://opsx.alibaba.com/mirror 镜像制作nginx镜像实例 创建并运行centos容器 ...