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 3294 Life Forms【SA+二分】

    先加入未出现字符间隔把n个串连起来,注意如果串开的char这个间隔字符不能溢出,把这个接起来的串跑SA,二分答案k,判断的时候把连续一段he>=k的分成一组,然后看着一段是否包含了>n/2 ...

  2. 7天学完Java基础之1/7

    方法重载 package cn.itcat.day04.demo01; //方法重载就是参数个数不同,参数类型不同,参数类型的顺序不同 //方法重载与参数名称无关,与方法返回值类型无关 //方法重载方 ...

  3. C. Coconut(2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛)

    额,只是一道签到题,emmm直接代码: #include <cstdio> #include <cstring> #include <algorithm> usin ...

  4. PMD - Avoid autogenerated methods to access private fields and methods of inner / outer classes

    PMD错误 Avoid autogenerated methods to access private fields and methods of inner / outer classes 样例 p ...

  5. SpringBoot | 问题 | 注解方式下无法发现Bean

    在排除注解的问题后,考虑扫描类的位置, [SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描! “Application类”是指SpringBoot项 ...

  6. sublime的几款实用插件

    1.CSScomb 用于调整css属性的书写顺序 2.Emmet 缩写神器 3.HTML/CSS/JS Prettify 代码格式化 4.Trimmer 去空格去空行 5.Alignment 代码对齐 ...

  7. input标签属性

    很多时候,我们都用到了很多标签实现输入功能,所以在这里梳理一下. 1.建立一个文本框 <input type="text" name="userName" ...

  8. P1320 压缩技术(续集版)

    题目描述 设某汉字由N X N的0和1的点阵图案组成,如下图.我们依照以下规则生成压缩码.连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从上到下,由左到右.第一个数表示连续有几个0 ...

  9. 序列化json模块

    1.用json模块来进行序列化和反序列化 注意:用json序列化的数据类型得到的文件后缀名必须是json.因为如果不是json后缀,别人也不知道这是用json序列化的文件. 序列化:json.dump ...

  10. [BZOJ1968][AHOI2005]COMMON约数研究 数学

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1968 直接计算每个因子的贡献就可以了. $Ans=\sum_{i=1}^n[\frac{n ...