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

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

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. CSS Modules入门教程

    为什么引入CSS Modules 或者可以这么说,CSS Modules为我们解决了什么痛点.针对以往我写网页样式的经验,具体来说可以归纳为以下几点: 全局样式冲突 过程是这样的:你现在有两个模块,分 ...

  2. babel-preset-env使用指南

    文章概览 babel-preset-env是非常重要且常用的一个插件预设,掌握它的用法以及实现原理非常有必要. 本文主要内容包括:babel-preset-env是什么.入门实例.如何配置以支持特定版 ...

  3. 并发连接MySQL

    先吐槽一下libmysqlclientAPI的设计, 多个线程同时去connect居然会core掉. 后来Google了一番, 才发现mysql_real_connect不是线程安全的, 需要一些额外 ...

  4. sqlserver2008 传入的表格格式数据流(tds)协议流不正确。

    起因是在sql 2008 里使用 sql prompt 报了一个内部连接致命错误,原本应该想到是数据库连接问题的,奇怪的是能连接上数据库也能查询表仅仅是用不了工具没有智能提示. 几经查询无果,度娘上之 ...

  5. 面向对象设计的SOLID原则、迪米特法则

    SPR(The Single Responsibility Principle):单一责任原则 OCP(The Open Closed Principle):开放封闭原则 LSP(The Liskov ...

  6. [转帖]漫画趣解Linux内核

    漫画趣解Linux内核 https://blog.csdn.net/juS3Ve/article/details/84207142 Linux 内核漫画 今天,我来为大家解读一幅来自 TurnOff. ...

  7. vue 动态插入组件

    HTML代码: <div id="app"> <p>{{ message }}</p> <button @click="add( ...

  8. Js中instanceof 的用法

    在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”. ...

  9. Microsoft Visual Studio Ultimate 2013密钥

    Visual Studio Ultimate 2013 KEY(密钥):BWG7X-J98B3-W34RT-33B3R-JVYW9Visual Studio Premium 2013 KEY(密钥): ...

  10. Oracle调优总结

    Oracle调优总结(经典实践 重要) https://blog.csdn.net/dtjiawenwang88/article/details/74892245 https://www.cnblog ...