1、字符串基础

1.1 字符集

一个字符集是一个建立了全序关系的集合,也就是说中的任意两个不两只的元素都可以比较大小,要么,要么。字符集中的元素称为字符。

1.2 字符串

一个字符串S是将n个字符顺次排列形成的序列,n称为S的长度,表示为。S的第i个字符表示为S[i]。

1.3 子串

字符串S的子串S[i..j],,表示S串中从i到j这一段,也就是顺次排列S[i], S[i+1],...,S[j]形成的字符串。

1.4 子序列

字符串S的子序列是从S中将若干元素提取出来并不改变相对位置形成的序列,即, 

1.5 后缀

后缀是指从某个位置i开始到整个串末尾结束的一个特殊子串。字符串S的从i开头的后缀表示为Suffix(S,i),也就是Suffix(S,i) = S[i..|S|-1]。

真后缀指除了S本身的S的后缀。

举例来说,字符串 abcabcd 的所有后缀为 {d, cd, bcd, abcd, cabcd, bcabcd, abcabcd},而它的真后缀为 {d, cd, bcd, abcd, cabcd, bcabcd}

1.6 前缀

前缀是指从串首开始到某个位置i结束的一个特殊子串。字符串S的以i结尾的前缀表示为Prefix(S,i),也就是Prefix(S,i)=S[0..i]。

真前缀指除了S本身的S的前缀。

举例来说,字符串 abcabcd 的所有前缀为 {a, ab, abc, abca, abcab, abcabc, abcabcd}, 而它的真前缀为 {a, ab, abc, abca, abcab, abcabc}。

1.7 字典序

以第i个字符作为第i关键字进行大小比较,空字符小于字符集内任何字符(即

1.8 回文串

回文串是正着写和倒着写相同的字符串。即满足的s。

2、前缀函数

给定一个长度为n的字符串s,其前缀函数被定义为一个长度为n的数组。其中的定义是

  • 如果子串s[0..i]有一对相等的真前缀与真后缀:s[0...k-1]和s[i-(k-1)...i],那么就是这个相等的真前缀的长度,也就是
  • 如果不止有一对相等的,那么就是其中最长的那一对的长度。
  • 如果没有相等的,那么

简单来说就是子串s[0...i]最长的相等的真前缀与真后缀的长度。

有数学语言描述如下

特别地,规定

2.1 朴素算法

按照定义计算前缀函数的算法流程

  1. 在一个循环中以的顺序计算前缀函数的值()
  2. 为了计算当前的前缀函数值,令变量j从最大的真前缀长度i开始尝试。
  3. 如果当前长度下真前缀与真后缀相等,则此时长度为,否则令j自减1,继续匹配,直到
  4. 如果并且仍没有任何一次匹配,则置=0,并移至下一个下标

实现如下:

vector<int> prefix_function(string s) {int n = (int)s.length();vector<int> pi(n);for (int i = 1; i < n; i++)for (int j = i; j >= 0; j--)if (s.substr(0, j) == s.substr(i - j + 1, j)) {pi[i] = j;break;}return pi;
}

2.2 优化算法一

基于相邻的前缀函数值至多增加1。

当相邻前缀函数值增加时,即多1时,满足。所 以当移到到下一个位置时,前缀函数的值要么增加1,要么维持不变,要么减少。

改进算法为

vector<int> prefix_function(string s) {int n = (int)s.length();vector<int> pi(n);for (int i = 1; i < n; i++)for (int j = pi[i - 1] + 1; j >= 0; j--)  // improved: j=i => j=pi[i-1]+1if (s.substr(0, j) == s.substr(i - j + 1, j)) {pi[i] = j;break;}return pi;
}

2.3 优化算法二

失配时,对于子串s[0...i],仅次于的第二长度j,使得在位置i的前缀性质仍得以保持,即。如果找到了这样的长度j,那么仅需要再次比较s[i+1]和s[j]。如果它们相等,那么有。否则,需要找到子串s[0...i]仅次于j的第二长度,使得前缀性质得以保持,如此反复,直到j=0。如果,则

对于第二长度j,因为,有。也就是说j等价于子串的前缀函数值,即。同理将于j的第二长度等价于s[j-1]的前缀函数值,即。关于j的状态转移方法为,

改进算法为:

vector<int> prefix_function(string s) {int n = (int)s.length();vector<int> pi(n);for (int i = 1; i < n; i++) {int j = pi[i - 1];while (j > 0 && s[i] != s[j]) j = pi[j - 1];if (s[i] == s[j]) j++;pi[i] = j;}return pi;
}

3、应用

3.1 字符串周期

对于字符串s和,若s[i] = s[i+p]对所有成立 ,则称p为s的周期。

对于字符串s和,若s长度为r的前缀和长度为r的后缀相等,就称s长度为r的前缀是s的border,则|s|-r是s的周期。

3.2 字符串查找

在文本串与模式串匹配时,使用前缀函数,代码如下

private boolean kmpSearch(String pattern, String text, int[] pi) {int textLen = text.length();int patternLen = pattern.length();int ans = 0;int j = 0;for (int i = 0; i < textLen; i++) {while (j > 0 && text.charAt(i) != pattern.charAt(j)) {j = pi[j - 1];}if (pattern.charAt(j) == text.charAt(i)) {j++;}if (j == patternLen) {return true;}}return false;}

另外一种解法是构造s+#+t的串,计算其前缀函数,判断|s|+1到|s|+1+|t|之间的前缀函数值是否等于模式串的长度。

3.3 构造自动机

先计算前缀函数,根据字符集构造自动机

private int[][] computeAutomation(String pattern) {int n = pattern.length();int[][] aut = new int[n][N];int[] pi = prefixFunction(pattern);for (int i = 0; i < n; i++) {for (int j = 0; j < N; j++) {if (i > 0 && 'a' + j != pattern.charAt(i)) {aut[i][j] = aut[pi[i - 1]][j];} else {aut[i][j] = i + (pattern.charAt(i) == 'a' + j ? 1 : 0);}}}return aut;}

3.4 前缀统计

根据前缀函数计算

int n = pattern.length();
int[] cnt = new int[n + 1];int[] pi = prefixFunction(pattern);
for (int i = 0; i < n; i++) {cnt[pi[i]]++;
}for (int i = n - 1; i > 0; i--) {cnt[pi[i - 1]] += cnt[i];
}for (int i = 0; i <= n; i++) {cnt[i]++;
}

LeetCode 686

455 Periodic Strings UVa

11022 String Factoring UVa

11452 Dancing the Cheeky-Cheeky UVa(kmp字符串周期)

12604 Caesar Cipher UVa (kmp查找)

12467 Secret Word UVa

11019 Matrix Matcher UVa (二维匹配问题)

Pattern Find SPOJ(字符口中匹配kmp)

Anthem of Berland codeforces(kmp+自动机+dp)

MUH and Cube Walls codeforces(kmp)

Prefixes and Suffixes codeforces(kmp+前缀统计)

参考资料:

字符串部分简介 - OI Wiki

https://cp-algorithms.com/

https://www-igm.univ-mlv.fr/~lecroq/ 字符串算法

前缀函数及kmp算法相关推荐

  1. KMP 算法 Kunth-Morris-Pratt

    Q:KMP是什么鬼,KMP卖的炸鸡还不错 A:你说的是KFC吧 Q:都一样,反正都是卖炸鸡的,最近买一整只黄金脆皮鸡还送中可 A:那吃好勒您 Q:咕噜咕噜... 学习Kunth-Morris-Prat ...

  2. KMP算法——子串匹配

    目录 1.什么是前缀函数 2.如何求前缀函数 3.解题思路 4.代码 KMP算法是一种字符串匹配算法,大大提高了字符串匹配的效率 例题:力扣28. 实现 strStr(),以下是根据该题的题解而写 1 ...

  3. c语言主范式与编码,超详细!终于搞明白KMP算法

    小伙伴们好久不见,今天将开设"数据结构与算法"专栏,一起梳理一遍硬核课程的重要知识点,那我们开始吧 正文 「字符串匹配」是计算机的基本任务之一,举个栗子,有一个字符串"「 ...

  4. 图解KMP算法,带你彻底吃透KMP

    模式串匹配--KMP算法 KMP算法一直是一个比较难以理解的算法,本篇文章主要根据<大话数据结构>中关于KMP算法的讲解,结合自己的思考,对于KMP算法进行一个比较详细的解释. 由于博主本 ...

  5. C语言-模式匹配(KMP算法)

    什么是KMP算法? KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,简称KMP算法.KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与 ...

  6. Knuth-Morris-Pratt 算法(KMP算法)

    Knuth-Morris-Pratt 算法,简称 \text{KMP}KMP 算法,由 \text{Donald Knuth}Donald Knuth.\text{James H. Morris}Ja ...

  7. 数据结构之串:KMP算法

    串:KMP算法 基本概念: KMP算法原理: KMP算法的代码实现: KMP算法的性能: 基本概念: 应用优化前提: 有部分匹配的前缀和后缀 KMP算法原理: 按普通的串的模式匹配算法,在1位置比较完 ...

  8. c语言数据结构kmp中next计算,数据结构——关于KMP算法中next函数的详细解析

    以前看到数据结构中字符串的模式匹配时,花了半天的时间,才把KMP算法中的next函数整明白了,结果过了几天在看到这时,只记得next[j+1]=next[j]+1,但是有时候能套公式正确算出,有时候就 ...

  9. 算法-发明KMP算法的唐纳德·克努特是怎么想到失配函数next[j]的?

    背景 字符串模式匹配,普通模式非常好理解,拿着模式串依次与主串做比较,知道完全匹配,但是这种算法,主串得不断地回溯,时间复杂度O(n*m). 唐纳德·克努特 有没有降低时间复杂度的可能,唐纳德·克努特 ...

最新文章

  1. 基于RSA的WEB前端密码加密方案
  2. .net 笔记尝试(二)
  3. 使用CSS控制段落首行缩进
  4. colorWithAlphaComponent
  5. python发音翻译-python实现在线翻译
  6. [电影]十七岁的单车
  7. 汇川技术小型PLC梯形图编程系列教程(零):梯形图编程学习指南
  8. k8s中各组件和kube apiserver通信时的认证和鉴权
  9. 浏览班级为计算机的同学记录的命令,2011年全国计算机等级考试二级VFP笔记(4)...
  10. 微信网页设置标题title
  11. 计算机显卡风扇有异响,电脑运行中有异响,拍一拍就好了,原来好多人还不知道问题在哪!...
  12. vue中使用阿里字体图标库
  13. 局域网互传文件工具_如何在 iOS、Android、macOS、Windows 之间快速文件互传?
  14. 设置linux睡眠时间,Linux 睡眠时间函数如何使用?延迟指定时间sleep命令了解一下...
  15. Golang多线程文件传输
  16. 第一章:基于Visual C++ 6.0使用运动控制卡控制电机转动实验操作指导
  17. UVA 12576 - Simply Loopy
  18. CentOS7中安装Tomcat8
  19. After Effects Guru: Mastering the Timeline After Effects Guru:掌握时间轴 Lynda课程中文字幕
  20. 问题 E: 完美立方

热门文章

  1. 2017.4.6AM
  2. 关于面试的一些问题合集
  3. java初始化实例化_Java 类初始化和实例化以及多态理解
  4. python安装步骤图解-Python安装-小白图文教程(精)
  5. python程序员需要掌握哪些技术-python运维要掌握哪些内容
  6. python turtle画熊-用Python Turtle 画可爱的熊猫
  7. 新手用python2还是3-新手用python2还是3
  8. python工资等级分类程序-php项目中用python来预测薪资(工资)
  9. python语言怎么学-怎么学Python语言呢?粤嵌Python学习路线入门
  10. python培训班那家好-Python培训机构去哪好