常用字符串匹配算法(brute force, kmp, sunday)
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
July. 从头到尾彻底理解KMP(2014年8月22日版)
常用字符串匹配算法(brute force, kmp, sunday)的更多相关文章
- 字符串匹配算法——BF、KMP、Sunday
一:Brute force 从源串的第一个字符开始扫描,逐一与模式串的对应字符进行匹配,若该组字符匹配,则检测下一组字符,如遇失配,则退回到源串的第二个字符,重复上述步骤,直到整个模式串在源串中找到匹 ...
- 数据结构(十六)模式匹配算法--Brute Force算法和KMP算法
一.模式匹配 串的查找定位操作(也称为串的模式匹配操作)指的是在当前串(主串)中寻找子串(模式串)的过程.若在主串中找到了一个和模式串相同的子串,则查找成功:若在主串中找不到与模式串相同的子串,则查找 ...
- 字符串匹配算法BF和KMP总结
背景 来看一道leetcode题目: Implement strStr(). Returns the index of the first occurrence of needle in haysta ...
- 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!
前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...
- Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化
1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...
- 字符串匹配算法 - KMP
前几日在微博上看到一则微博是说面试的时候让面试者写一个很简单的字符串匹配都写不出来,于是我就自己去试了一把.结果写出来的是一个最简单粗暴的算法.这里重新学习了一下几个经典的字符串匹配算法,写篇文章以巩 ...
- 字符串模式匹配算法--BF和KMP详解
1,问题描述 字符串模式匹配:串的模式匹配 ,是求第一个字符串(模式串:str2)在第二个字符串(主串:str1)中的起始位置. 注意区分: 子串:要求连续 (如:abc 是abcdef的子串) ...
- KMP单模快速字符串匹配算法
KMP算法是由Knuth,Morris,Pratt共同提出的算法,专门用来解决模式串的匹配,无论目标序列和模式串是什么样子的,都可以在线性时间内完成,而且也不会发生退化,是一个非常优秀的算法,时间复杂 ...
- 字符串匹配算法——KMP算法学习
KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...
随机推荐
- python 之 配置环境变量、通过pip 安装第三方库
配置环境变量 右击桌面上的“此电脑”—>“属性”—>“高级系统设置”—>右下角“环境变量”—>双击“系统变量”里的“Path”—>点击“新建”—>输入python的 ...
- python __builtins__ bytes类 (8)
8.'bytes', 字符串转换成字节流.第一个传入参数是要转换的字符串,第二个参数按什么编码转换为字节. class bytes(object) | bytes(iterable_of_ints) ...
- servlet重定向到jsp后样式无法正常显示
原因是在servlet中转发时css和图片的路径变成相对于这个servlet的相对路径而非相对于web项目的路径了. 解决办法:导入css样式和图片时把css写成动态绝对路径, 如用EL表达式表示: ...
- SpringBoot自定义参数解析器
一.背景 平常经常用 @RequestParam注解来获取参数,然后想到我能不能写个自己注解获取请求的ip地址呢?就像这样 @IP String ip 二.分析 于是开始分析 @RequestPara ...
- 利用uiautomator实现Android移动app启动时间的测试
为了减少因手工测试的反应误差,这里介绍下如何利用Android自带的自动化测试工具uiautomator实现app启动时间的测试. 测试基本思路如下: 1.启动前记录当前的时间戳 2.启动app,直至 ...
- AJPFX的内存管理小结
管理范围:任何继承于 NSObject的对象原理:每一个对象都有引用计数器当使用alloc new 和 copy创建对象时引用计数器被设置为1给对象发送一条retain消息 ,引用计数器加1 ...
- 做OJ项目时遇到的坑
1.js代码写在Dom加载前,导致highcharts在ie8能够显示,而ie高版本和其他浏览器不能显示 我的理解:由于IE8和其他浏览器的js解析机制不同,ie8是在等dom全部加载完才开始执行js ...
- react基础语法(三)组件的创建和复合组件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- [Python3]Python官方文档-Python Manuals
简介 一般情况下,初学者都不愿意直接去浏览Python Manuals,即Python自带的官方文档.尤其是只有英文版的情况下,初学者更加不会去使用该官方文档了. 在这里笔者强力推荐初学者经常学会使用 ...
- win10忘记wifi记录
1.点击桌面右下角无线图标 2.点击网络设置 3.点击管理WIFI设置 4.点击要管理的账户,忘记或者共享该wifi.