1. 传统的字符串匹配算法

传统匹配思想是,从目标串Target的第一个字符开始扫描,逐一与模式串的对应字符进行匹配,若该组字符匹配,则检测下一组字符,如遇失配,则退回到Target的第二个字符,重复上述步骤,直到整个Pattern在Target中找到匹配,或者已经扫描完整个目标串也没能够完成匹配为止。

这种算法的就是包括两个循环, 设Target串的长度是n, Pattern串的长度是m, 那么复杂度是O(m*n)

参考代码:

void NativeStrMatching( ElemType Target[], ElemType Pattern[] )
{register int TarLen = 0; // Length of Targetregister int PatLen = 0; // Length of Pattern// Compute the length of Patternwhile( '\0' != Pattern[PatLen] )PatLen++;while( '\0' != Target[TarLen] ){int TmpTarLen = TarLen;for(int i=0; i<PatLen; i++){if( Target[TmpTarLen++] != Pattern[i] )break;if( i == PatLen-1 )cout<<"Native String Matching,pattern occurs with shift "<<TarLen<<endl;}TarLen++;}
}

C++代码:

void NativeStrMatch(const string& target,const string& pattern){int n=target.size();int m=pattern.size();for(int i=0;i<n;i++){int k=i;int j;for(j=0;j<m&&target[k]==pattern[j];k++,j++);if(j==m){cout<<"Native string Matching occurs at "<<i<<endl;}}
}

2. KMP算法

传统算法虽然简单易行,但其中包含了过多的不必要操作,并不能很好地达到实际工作中需要的效率.

KMP算法就能很好地解决这个冗余问题。

其主要思想为:

在失配后,并不简单地从目标串下一个字符开始新一轮的检测,而是依据在检测之前得到的有用信息(稍后详述),直接跳过不必要的检测,从而达到一个较高的检测效率。

KMP算法主要包括计算前缀数组以及利用这个前缀数组进行判断.

前缀计算的参考代码:

// Compute Prefix function
void CptPfFunc( ElemType Pattern[], int PrefixFunc[] )
{register int iLen = 0; // Length of Pattern[]while( '\0' != Pattern[iLen] )iLen++;int LOLP = 0; // Lenth of longest prefixPrefixFunc[1] = 0;for( int NOCM=2; NOCM<iLen+1; NOCM++ ) // NOCM represent the number of characters matched
    {while( LOLP>0 && (Pattern[LOLP] != Pattern[NOCM-1]) )LOLP = PrefixFunc[LOLP];if( Pattern[LOLP] == Pattern[NOCM-1] )LOLP++;PrefixFunc[NOCM] = LOLP;}
}

利用前缀进行匹配的KMP算法参考代码:

void KMPstrMatching( ElemType Target[], ElemType Pattern[] )
{int PrefixFunc[MAX_SIZE];register int TarLen = 0;register int PatLen = 0;// Compute the length of array Target and Patternwhile( '\0' != Target[TarLen] )TarLen++;while( '\0' != Pattern[PatLen] )PatLen++;// Compute the prefix function of Pattern
    CptPfFunc( Pattern, PrefixFunc );int NOCM = 0; // Number of characters matchedfor( int i=0; i<TarLen; i++ ){while( NOCM>0 && Pattern[NOCM] != Target[i] )NOCM = PrefixFunc[NOCM];if( Pattern[NOCM] == Target[i] )NOCM++;if( NOCM == PatLen ){cout<<"KMP String Matching,pattern occurs with shift "<<i - PatLen + 1<<endl;NOCM = PrefixFunc[NOCM];}}
}

完整的KMP算法对应的C++代码如下:

#include <iostream>
#include <string>
using namespace std;
//compute prefix function
void CptPfFunc(const string& pattern,int* prefix){size_t m=pattern.size();int j=0;//length of longest prefixprefix[1]=0;for(int i=2;i<=m;i++){while(j>0&&pattern[j]!=pattern[i-1])j=prefix[j];if(pattern[j]==pattern[i-1])j++;prefix[i]=j;}
}
void KMPstrMatch(const string& target,const string& pattern){int n=target.size();int m=pattern.size();int *prefix=new int[m+1];CptPfFunc(pattern,prefix);int j=0;for(int i=0;i<n;i++){while(j>0&&pattern[j]!=target[i])j=prefix[j];if(pattern[j]==target[i])j++;if(j==m){cout<<"KMP string Matching occurs at "<<i-j+1<<endl;j=prefix[j];}}delete [] prefix;
}

参考:

http://billhoo.blog.51cto.com/2337751/411486

http://www.matrix67.com/blog/archives/115/

11.Algorithm Gossip: 字符串核对

说明今日的一些高阶程序语言对于字符串的处理支持越来越强大(例如Java、Perl等),不过字符串搜寻本身仍是个值得探讨的课题,在这边以Boyer- Moore法来说明如何进行字符串说明,这个方法快且原理简洁易懂。

解法字符串搜寻本身不难,使用暴力法也可以求解,但如何快速搜寻字符串就不简单了,传统的字符串搜寻是从关键字与字符串的开头开始比对,例如 Knuth-Morris-Pratt 算法字符串搜寻,这个方法也不错,不过要花时间在公式计算上;Boyer-Moore字符串核对改由关键字的后面开始核对字符串,并制作前进表,如果比对不符合则依前进表中的值前进至下一个核对处,假设是p好了,然后比对字符串中p-n+1至p的值是否与关键字相同。

那麼前進表該如何前進,舉個實際的例子,如果要在字串中搜尋JUST這個字串,則可能遇到的幾個情況如下所示:

依照這個例子,可以決定出我們的前進值表如下:

其它

J

U

S

T

4

3

2

1

4(match?)

如果关键字中有重复出现的字符,则前进值就会有两个以上的值,此时则取前进值较小的值,如此就不会跳过可能的位置,例如texture这个关键字,t的前进值应该取后面的3而不是取前面的7。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void table(char*); // 建立前进表
int search(int, char*, char*); // 搜寻关键字
void substring(char*, char*, int, int); // 取出子字符串
int skip[256];
int main(void) { char str_input[80]; char str_key[80]; char tmp[80] = {'\0'}; int m, n, p; printf("请输入字符串:"); gets(str_input); printf("请输入搜寻关键字:"); gets(str_key); m = strlen(str_input); // 计算字符串长度n = strlen(str_key); table(str_key); p = search(n-1, str_input, str_key); while(p != -1) { substring(str_input, tmp, p, m); printf("%s\n", tmp); p = search(p+n+1, str_input, str_key); } printf("\n"); return 0;
}
void table(char *key) { int k, n; n = strlen(key); for(k = 0; k <= 255; k++) skip[k] = n; for(k = 0; k < n - 1; k++) skip[key[k]] = n - k - 1;
}
int search(int p, char* input, char* key) { int i, m, n; char tmp[80] = {'\0'}; m = strlen(input); n = strlen(key); while(p < m) { substring(input, tmp, p-n+1, p); if(!strcmp(tmp, key)) // 比较两字符串是否相同return p-n+1; p += skip[input[p]]; } return -1;
}
void substring(char *text, char* tmp, int s, int e) { int i, j; for(i = s, j = 0; i <= e; i++, j++) mp[j] = text[i]; tmp[j] = '\0';
}

转载于:https://www.cnblogs.com/xkfz007/archive/2012/11/13/2767405.html

算法题-字符串匹配算法相关推荐

  1. 算法题字符串“~asd;4#1ebr67qwe234#13sdBd1d1,@3ret#156ghk123#1A34D”

    算法题字符串"~asd;4#1ebr&67qwe234#1&3sdBd1d1,@3ret#1&56ghk123#1A&34D" 使用3 个线程 a, ...

  2. js实现kmp算法_字符串匹配算法KMP算法

    数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...

  3. 【算法篇-字符串匹配算法】BF算法和KMP算法

    目录 前言 1. BF算法 1.1 画图分析 1.3 BF 算法的时间复杂度 2. KMP 算法 2.1 KMP 算法和 BF 算法 的区别 2.1.1 为什么主串不回退? 2. 2 next 数组 ...

  4. leetcode算法题--字符串的排列

    原题链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/ vector<string> res; vector& ...

  5. leetcode算法题--字符串转换整数 (atoi)

    原题链接: https://leetcode-cn.com/problems/string-to-integer-atoi/ https://leetcode-cn.com/problems/ba-z ...

  6. leetcode算法题--字符串相乘

    原文链接:https://leetcode-cn.com/problems/multiply-strings/ 思路如图(来源): string multiply(string num1, strin ...

  7. 算法导论笔记:32字符串匹配算法

    在编辑文本程序中,经常需要在文本中找到某个模式的所有出现位置.典型的情况是:在一个文本文件中,搜索用户输入的关键字.解决这种问题的算法叫做字符串匹配算法.字符串匹配算法的形式化定义如下:假设文本是长度 ...

  8. c++ 字符串匹配算法sunday算法

    sunday 算法是一种很高效的字符串匹配算法, 其实现也较kmp算法简单很多 class Sunday {public:const string& needle;int mp[300];Su ...

  9. 经典算法题:字典树、并查集、单调栈、二分、带标记函数dp、树、全排列、字符串问题等常用算法

    0. Tips 1. 位运算 如何枚举一个二进制状态数字k的子集, 方法就是针对中的二进制为1的位开始进行减法,判断数字k的二进制子集, 像枚举(2^k-1) ~ 0一样枚举其子集: int sub ...

  10. 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)

    图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...

最新文章

  1. redis在PHP中的基本使用案例
  2. MySQL force Index 强制索引概述
  3. 第十四届智能车竞赛规则浅聊
  4. LeetCode-726. 原子的数量(python2)
  5. MySQL数据库:常见经典SQL语句
  6. mysql2012用户名_SQL Server 登录名、服务器角色、用户名和数据库角色 --- 解释
  7. Linux的open函数的调用过程,Linux 中open系统调用实现原理
  8. 【VS 2017 C语言 汇编语言】如何使用VS 2017,通过反汇编查看C语言代码对应的32位x86汇编语言 VS 2017单步调试的使用
  9. 计算机应用技术专业课程改革方案,【计算机维护论文】计算机应用技术专业教学改革方案(共4015字)...
  10. 面试题,你什么时候可以入职?回答不好,容易被压薪资
  11. [转]RTH试用手记之“额外功能”
  12. Unity3D倒计时两种方法
  13. 安卓优质大作业 前后端 通讯+社区+志愿服务功能
  14. Xshell 6 的使用
  15. Excel如何一键改色
  16. 搭建qnx开发环境,虚拟qnx系统+虚拟win7系统+QNX Momentics IDE 4.6
  17. 数据集成工具 —— datax与flinkx的使用
  18. 计算机找不到无线设备,win10找不到无线设备怎么办_win10电脑找不到无线设备如何解决...
  19. 文墨绘学艺术学堂邀请中国书法学会副会长锻铁林弘扬中国“正统书法”
  20. 数据湖有新解!Apache Hudi 与 Apache Flink 集成

热门文章

  1. 从零基础入门Tensorflow2.0 ----三、6. 实战tf.constant
  2. Mat矩阵和数组的运算
  3. 创建一棵二叉树(C++)以及遍历
  4. matlab在遥感数字图像处理方面的应用
  5. python 爬虫基础(一)Beautifulsoup基础介绍
  6. java做一个简单的银行账户演示程序_JAVA初学(七):银行账户演示程序
  7. python函数参数为文件名_从零开始第5步:Python 函数和模块
  8. 物理机安装linux系统,物理机安装linux的三种方法
  9. 项目:文本相似度分析(C++)
  10. 在vscode中使用ajax,vscode中的ajax片段,