1. 暴力解法

// 暴力求解
int Idx(string S, string T){
// 返回第一个匹配元素的位置,若没有匹配的子串,则返回-1
int S_size = S.length();
int T_size = T.length();
if(S_size == T_size && S_size == )
return ;
if(S_size < T_size)
return -; int head = ;
int i = head;
int j = ; while(i < S_size && j < T_size){
if(S[i] == T[j]){
++i;
++j;
if(j == T_size && i <= S_size)
return head;
}
else{
++head;
i = head;// i回溯, 在kmp算法中,i不会出现回溯,即i值不会减小
j = ;
}
}
return -;
}

2. KMP (包括返回第一个匹配字符串的位置和返回所有匹配字符串的位置)

void PartialMatchTable(string s, int next[]){
int len = s.length();
next[] = -;
int i = ;
int j = -; while(i < len){
if(j == - || s[i] == s[j]){
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
} int kmp(string s, string p){
int s_size = s.length();
int p_size = p.length(); int next[p_size];
PartialMatchTable(p, next);
int i = ;
int j = ;
while(i < s_size && j < p_size){
if(j == - || s[i] == p[j]){
i++;
j++;
}
else{
j = next[j];
}
}
if(j == p_size)
return i-j;
else
return -;
} // kmp_vec(string s, string p)找出所有匹配位置
vector<int> kmp_vec(string s, string p){
int s_size = s.length();
int p_size = p.length();
vector<int> pos; int next[p_size];
PartialMatchTable(p, next);
int i = ;
int j = ;
while(i < s_size && j < p_size){
if(j == - || s[i] == p[j]){
i++;
j++;
if(j == p_size){
pos.push_back(i-j);
j = ;
}
}
else{
j = next[j];
}
} if(pos.size() == )
pos.push_back(-);
return pos;
}

3. Sunday

int SundaySearch(string t, string p){
int t_size = t.size();
int p_size = p.size(); if(p_size <= || t_size <= )
return -; int i = , j = ;
int k;
int m = p_size;
while(i < t_size){
if(t[i] != p[j]) {// 不相等
for(k = p_size-; k>=; --k) {
if(p[k] == t[m])
break;
}
// i = i + p_size - k;
i = m - k;
j = ;
m = i + p_size;
}
else { // 相等,比较下一个字符
i++;
j++;
if(j == p_size)
return i-j;
}
}
return -;
}

4. 完整代码

/*
* @Author: z.c.wang
* @Email: iwangzhengchao@gmail.com
* @Last Modified time: 2019-01-23 14:39:58
*/
#include<iostream>
#include<string>
using namespace std; /**
* 方法1. brute force
* 方法2. KMP (kmp_next, kmp_dfa)
* 方法3. Sunday
*/ /**
* brute_force description:
* 暴力求解,在字符串s中匹配字符串p
* @param t [text, 文本串]
* @param p [pattern, 模式串]
* @return [若s含有p, 则返回第一个匹配的位置,否则,返回-1]
*/
int brute_force(string t, string p){
int t_size = t.length();
int p_size = p.length();
if(t_size == p_size && t_size == )
return ;
if(t_size < p_size)
return -; int head = ;
int i = head;
int j = ;
while(i < t_size && j < p_size){
if(t[i] == p[j]){
i++;
j++;
if(j == p_size && i <= t_size)
return head;
}
else{
head++;
i = head;
j = ;
}
}
return -;
} // 暴力求解的另一种写法
int brute_force2(string t, string p){
int t_size = t.length();
int p_size = p.length(); if(t_size == p_size && t_size == )
return ;
if(t_size < p_size)
return -; int i, j;
for(i = , j = ; i < t_size && j < p_size; i++){
if(t[i] == p[j]){
j++;
}
else{
i -= j;
j = ;
}
}
if(j == p_size) // 找到匹配
return i - j;
else // 为找到匹配
return -;
} /**
* ParticalMatchTable description:
* 对字符串p生成next数组
* @param p [pattern string]
* @param next [next数组]
*/
void ParticalMatchTable(string p, int next[]){
int i = ;
int j = -;
next[] = -; while(i < p.length()){
if(j == - || p[i] == p[j]){
i++;
j++;
next[i] = j;
}
else{
j = next[j];
}
}
} /**
* kmp algorithm based on next
* kmp_next algorithm
* @param t [text string]
* @param p [pattern string]
* @return [若s含有p, 则返回第一个匹配的位置,否则,返回-1]
*/
int kmp_next(string t, string p){
int t_size = t.length();
int p_size = p.length();
int next[p_size];
ParticalMatchTable(p, next); int i = ;
int j = ;
while(i < t_size && j < p_size){
if(j == - || t[i] == p[j]){
i++;
j++;
}
else{
j = next[j];
}
}
if(j == p_size)
return i-j;
else
return -;
} /*kmp algorithm based on dfa */
int kmp_dfa(string t, string p){
int row = ;
int col = p.length(); // 动态分配数组并初始化
int** dfa = new int*[row];
for(int i = ; i < row; i++)
dfa[i] = new int[col];
for(int i = ; i < row ; i++)
for(int j = ; j < col; j++)
dfa[i][j] = ; // 计算dfa
dfa[p[]][] = ;
for (int j = , x = ; j < col; ++j) {
for (int i = ; i < row; ++i)
dfa[i][j] = dfa[i][x];
dfa[p[j]][j] = j + ;
x = dfa[p[j]][x];
} // kmp algo
int i, j;
int t_size = t.length();
int p_size = p.length();
for (i = , j = ; i < t_size && j < p_size; i++){
j = dfa[t[i]][j];
}
if(j == p_size)
return i-j;
else
return -;
} /**
* [Sunday description]
* @param t [description]
* @param p [description]
* @return [description]
*/
int Sunday(string t, string p){
int t_size = t.length();
int p_size = p.length();
if(p_size == t_size && t_size == )
return ;
if(p_size < || t_size < )
return -; int i = ;
int j = ;
int k;
int m = p_size;
while(i < t_size){
if(t[i] != p[j]){
for(k = p_size-; k >= ; --k){
if(p[k] == t[m])
break;
}
i = m - k;
j = ;
m = i + p_size;
}
else{
i++;
j++;
if(j == p_size)
return i-j;
}
}
return -;
} /**
* [main description]
* @param argc [description]
* @param argv [description]
* @return [description]
*/
int main(int argc, char const *argv[])
{
string t = "bbc abcdab abcdabcdabde";
string p = "abcdabd";
// brute force
cout<<"brute_force : "<<brute_force(t, p)<<endl;
// kmp_next
cout<<"kmp_next : "<<kmp_next(t, p)<<endl;
// kmp_dfa
cout<<"kmp_dfa : "<<kmp_dfa(t, p)<<endl;
// Sunday
cout<<"Sunday : "<<Sunday(t, p)<<endl;
cout<<endl;
return ;
}

5. 运行结果

brute_force :
kmp_next :
kmp_dfa :
Sunday :

6. 资料

D.M. Sunday: A Very Fast Substring Search Algorithm. Communications of the ACM

阮一峰. 字符串匹配的KMP算法

July. 从头到尾彻底理解KMP(2014年8月22日版)

常用字符串匹配算法(brute force, kmp, sunday)的更多相关文章

  1. 字符串匹配算法——BF、KMP、Sunday

    一:Brute force 从源串的第一个字符开始扫描,逐一与模式串的对应字符进行匹配,若该组字符匹配,则检测下一组字符,如遇失配,则退回到源串的第二个字符,重复上述步骤,直到整个模式串在源串中找到匹 ...

  2. 数据结构(十六)模式匹配算法--Brute Force算法和KMP算法

    一.模式匹配 串的查找定位操作(也称为串的模式匹配操作)指的是在当前串(主串)中寻找子串(模式串)的过程.若在主串中找到了一个和模式串相同的子串,则查找成功:若在主串中找不到与模式串相同的子串,则查找 ...

  3. 字符串匹配算法BF和KMP总结

    背景 来看一道leetcode题目: Implement strStr(). Returns the index of the first occurrence of needle in haysta ...

  4. 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!

    前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...

  5. Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化

    1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...

  6. 字符串匹配算法 - KMP

    前几日在微博上看到一则微博是说面试的时候让面试者写一个很简单的字符串匹配都写不出来,于是我就自己去试了一把.结果写出来的是一个最简单粗暴的算法.这里重新学习了一下几个经典的字符串匹配算法,写篇文章以巩 ...

  7. 字符串模式匹配算法--BF和KMP详解

    1,问题描述 字符串模式匹配:串的模式匹配 ,是求第一个字符串(模式串:str2)在第二个字符串(主串:str1)中的起始位置. 注意区分: 子串:要求连续   (如:abc 是abcdef的子串) ...

  8. KMP单模快速字符串匹配算法

    KMP算法是由Knuth,Morris,Pratt共同提出的算法,专门用来解决模式串的匹配,无论目标序列和模式串是什么样子的,都可以在线性时间内完成,而且也不会发生退化,是一个非常优秀的算法,时间复杂 ...

  9. 字符串匹配算法——KMP算法学习

    KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...

随机推荐

  1. 【POJ - 3190 】Stall Reservations(贪心+优先队列)

    Stall Reservations 原文是English,这里直接上中文吧 Descriptions: 这里有N只 (1 <= N <= 50,000) 挑剔的奶牛! 他们如此挑剔以致于 ...

  2. 如何让Android微博个人详情页滚动到顶部

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/103 个人详情页滑动到顶部 最近产品提了个新需求,需要实现 ...

  3. flask跨域问题

    在Flask开发RESTful后端时,前端请求会遇到跨域的问题.下面是解决方法: 使用 flask-cors库可以很容易的解决   1 pip install flask-cors 两种方法,一个是全 ...

  4. 构造 Bubble Cup 8 - Finals D. Tablecity

    题目传送门 题意:在1000*2的格子里,在每个小时能派出两个警察在两个地点搜查小偷,求在2015小时内能抓住小偷的方案. 分析:首先每次扫过一列即i1 i2从左往右扫,这样会漏掉小偷正好从间隙穿过的 ...

  5. jsp问题记录

    2014-10-10 20:53:16 Jsp的el表达式:‘${value}’  用于获取后台传过来的值 而<%=value %>则是获取当前页面java代码的值

  6. selenium2+python自动化1-操作浏览器

    随着测试行业的发展,现在不论在找工作还是在实际的工作中,对要求掌握自动化越来越普遍,在这里就记录一下一些入门的知识,希望对阅读者能有一些帮助吧!好哒,步入正题,这一篇主要记录下如何用Python调用w ...

  7. SAMBA服务初学练习

    服务概述 Samba最先在Linux和Windows之间架起了一座桥梁,正是由于Samba的出现,我们可以在Linux和Windows之间实现文件共享的相互通讯,我们可以将其架设成一个功能非常强大的文 ...

  8. Sublime3注册码和安装中文包

    1.Sublime3注册码 在工具栏Help中点击Enter license,粘贴下面一大串 —– BEGIN LICENSE —– Michael Barnes Single User Licens ...

  9. 数位dp知识

    转自http://blog.csdn.net/zhaoxinfan/article/details/8707605 下面先给出数位DP的背景: •在给定区间[A,B]内,找满足要求的数. •要求一般和 ...

  10. zoj3772Calculate the Function(矩阵+线段树)

    链接 表达式类似于斐波那契 但是多了一个变量 不能用快速幂来解 不过可以用线段树进行维护 对于每一个点够一个2*2的矩阵 1 a[i] 1  0   这个矩阵应该不陌生 类似于构造斐波那契的那个数列 ...