来源:http://blog.csdn.net/qq_34494458/article/details/75253466

KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其对于任何模式和目标序列,都可以在线性时间内完成匹配查找,而不会发生退化,是一个非常优秀的模式匹配算法。

/*
* next[]的含义(前提):x[i-next[i]...i-1] = x[0...next[i]-1]这很重要;
* next[i]为满足x[i-z...i-1] = x[0...z-1]的最大值z(就是x的自身匹配);
*/ //求next的代码实现
/*
* next[]求到了next[m],这个next[m]作用还很大;
*/
void kmp_pre(char x[], int m, int next[]) {
int i, j;
j = next[0] = -1;
i = 0;
while (i < m) {
while (-1 != j && x[i] != x[j]) j = next[j];
//j = -1,表示第0位都没匹配成功;那就要直接推进一位;
next[++i] = ++j;
}
} /*
*还可以有一个小优化;
*/
void preKMP(char x[], int m, int kmpNext[]) {
int i, j;
j = kmpNext[0] = -1;
i = 0;
while (i < m) {
while (-1 != j && x[i] != x[j]) j = kmpNext[j];
if (x[++i] == x[++j]) kmpNext[i] = kmpNext[j];
else kmpNext[i] = j;
/*这个if很6,这除去了一些无意义的next[],大概意思是
*如果x[j]匹配失败了,那么就执行 j = next[j];
*而x[j] = x[next[j]]所以x[next[j]]肯定也会匹配失败。
*所以就说这个next[j]是无意义的。
*/
}
} /*
*x与y匹配;
*返回x在y中出现的次数,可以重叠
*与求next[]函数的写法基本相似;
*/ int next[10010];
int KMP_Count(char x[], int m, char y[], int n) {
//x是模式串,y是主串;
int i, j;
int ans = 0;
//preKMP(x, m, next);
kmp_pre(x, m, next);
i = j = 0;
while (i < n) {
while (-1 != j && y[i] != x[j]) j = next[j];
i++; j++;
if (j >= m) {
ans++;
j = next[j];
}
}
return ans;
}

经典题目:

加一个题目:http://poj.org/problem?id=3167

/*
*模式串可以浮动的模式串匹配问题
*给出模式串的相对大小,需要找出模式串匹配次数和位置
*比如说模式串: 1,4,4,2,3,1 而主串:5,6,2,10,10,7,3,2,9
*那么子串:2,10,10,7,3,2就是和模式串匹配的。
*思路:只需比较前面比当前数小的数与等于当前数的数的个数就好了,看这两个东西是否相等来进行kmp。
*/
//#include<bits/stdc++.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long LL;
#define lson k<<1, ll, mid
#define rson k<<1|1, mid+1, rr
const int MAXN = 100008;
int n, k, s, next[MAXN>>2], as[MAXN][26], bs[MAXN>>2][26], a[MAXN], b[MAXN];
vector<int> ans; void init() {//把输入的字符串同化成as和bs;
scanf("%d%d%d", &n, &k, &s);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
if (i != 0) {
for(int j = 1; j < 26; j++)
as[i][j] = as[i-1][j];
}
as[i][a[i]]++;
}
for(int i = 0; i < k; i++) {
scanf("%d", &b[i]);
if (i != 0) {
for(int j = 1; j < 26; j++)
bs[i][j] = bs[i-1][j];
}
bs[i][b[i]]++;
}
} //这里是没有嵌套while循环的写法,都是一样的。
void build_next() {
next[0] = -1;
next[1] = 0;//这里皮了一下
int j = 0, i = 1;
while (i < k) {
int t11 = 0, t12, t21 = 0, t22;
for(int t = 1; t < b[i]; t++)
if (i == j) t11 += bs[i][t];
else t11 += (bs[i][t]-bs[i-j-1][t]);
if (i == j) t12 = bs[i][b[i]];
else t12 = bs[i][b[i]]-bs[i-j-1][b[i]];
for(int t = 1; t < b[j]; t++)
t21 += bs[j][t];
t22 = bs[j][b[j]];
if (t11 == t21 && t12 == t22)
next[++i] = ++j;
else j = next[j];
}
} void kmp() {
ans.clear();
build_next();
int i = 0, j = 0;
while (i < n) {
int t11 = 0, t12, t21 = 0, t22;
for(int t = 1; t < a[i]; t++)
if (i == j) t11 += as[i][t];
else t11 += (as[i][t]-as[i-j-1][t]);
if (i == j) t12 = as[i][a[i]];
else t12 = as[i][a[i]]-as[i-j-1][a[i]];
for(int t = 1; t < b[j]; t++)
t21 += bs[j][t];
t22 = bs[j][b[j]];
if (t11 == t21 && t12 == t22) {
++i; ++j;
if (j >= k) {
ans.push_back(i-j+1);
j = next[j];
}
}
else j = next[j];
}
} int main() {
//freopen("in.txt", "r", stdin);
init();
kmp();
printf("%d\n", s = ans.size());
for(int i = 0; i < s; i++)
printf("%d\n", ans[i]);
return 0;
}

kmp算法 汇总的更多相关文章

  1. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  2. KMP算法

    KMP算法是字符串模式匹配当中最经典的算法,原来大二学数据结构的有讲,但是当时只是记住了原理,但不知道代码实现,今天终于是完成了KMP的代码实现.原理KMP的原理其实很简单,给定一个字符串和一个模式串 ...

  3. 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)

    前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...

  4. KMP算法实现

    链接:http://blog.csdn.net/joylnwang/article/details/6778316 KMP算法是一种很经典的字符串匹配算法,链接中的讲解已经是很明确得了,自己按照其讲解 ...

  5. 排序算法汇总(C/C++实现)

    前言:     本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的 ...

  6. 数据结构与算法JavaScript (五) 串(经典KMP算法)

    KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配 ...

  7. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

  8. 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案

    之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...

  9. 算法:KMP算法

    算法:KMP排序 算法分析 KMP算法是一种快速的模式匹配算法.KMP是三位大师:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,所以取首字母组成KMP. 少部分图片来自孤~影 ...

随机推荐

  1. kvm虚拟化网络管理(5)

    一.Linux Bridge网桥管理 网络虚拟化是虚拟化技术中最复杂的部分,也是非常重要的资源. 第一节中我们创建了一个名为br0的linux-bridge网桥,如果在此网桥上新建一台vm,如下图: ...

  2. Qt 设置中文

    1. 前言 在编写Qt应用程序时,有时会希望能直接设置中文字符串到界面,总结下其设置方法. 2. 设置中文 1)运行环境Qt5.5 VS2013 2)首先,查看需要设置中文的文件是否为UTF-8格式, ...

  3. 使用 JavaScript 将 HTML 转换为 PDF

    使用 JavaScript 将 HTML 转换为 PDF 更多相关学习资料参见http://www.pdfdownload.cn/b/ba_index.php 在本文中,我们将了解如何在浏览器(即完全 ...

  4. GO学习-(8) Go语言基础之数组

    Go语言基础之数组 Array(数组) 数组是同一种数据类型元素的集合. 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化. 基本语法: // 定义一个长度为3元素类型为 ...

  5. clone() java 简单的复制

      Java的复制有的 deepcopy 和 shapecopy 之分,这里简单的采用shapecopy  的 clone ( ) 方法, 但是指向的是同一个对象, 关于对象的问题,这里不做展开: / ...

  6. 开源项目核心商城(CoreShop)

    帮小伙伴推一下他的开源项目作者是@大灰灰 核心商城(CoreShop)Beta 支持可视化布局的.Net小程序商城 [![star](https://gitee.com/CoreUnion/CoreS ...

  7. AI框架精要:设计思想

    AI框架精要:设计思想 本文主要介绍飞桨paddle平台的底层设计思想,可以帮助用户理解飞桨paddle框架的运作过程,以便于在实际业务需求中,更好的完成模型代码编写与调试及飞桨paddle框架的二次 ...

  8. TensorFlow csv读取文件数据(代码实现)

    TensorFlow csv读取文件数据(代码实现) 大多数人了解 Pandas 及其在处理大数据文件方面的实用性.TensorFlow 提供了读取这种文件的方法. 前面章节中,介绍了如何在 Tens ...

  9. 如何使用Intel vtune profilier?

    如何使用Intel vtune profilier?

  10. 【NX二次开发】Block UI 选择小平面区域

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...