一.字符串匹配算法

(1)传统匹配算法BF

  1. int Index_BF(char* S, char* T){
  2. int i=1,j=1;
  3. while(i<=strlen(S) && j<=strlen(T)){
  4. if(S[i]==T[j]){
  5. ++i;
  6. ++j;
  7. }
  8. else{
  9. i=i-j+2;
  10. j=1;
  11. }
  12. }
  13. if(j>strlen(T))
  14. return i - strlen(T);
  15. else
  16. return 0;
  17. }

(2)KMP

  1. void get_next(char* T, int next[]){
  2. int i=1,j=0;
  3. next[1]=0;
  4. while(i<strlen(T)){
  5. if(j==0||T[i]==T[j]){
  6. ++i;
  7. ++j;
  8. next[i]=j;
  9. }
  10. else
  11. j=next[j];
  12. }
  13. }
  14. int Index_KMP(char* S, char* T, int next[]){
  15. int i=1, j=1;
  16. while (i<=strlen(S)&&j<=strlen(T)){
  17. if(j==0||S[i]==T[j]){
  18. ++i;
  19. ++j;
  20. }
  21. else
  22. j=next[j];
  23. }
  24. if(j>strlen(T))
  25. return i-strlen(T);
  26. else
  27. return 0;
  28. }

(3)KMP改进算法

  1. void get_nextval(char* T,int nextval[]){
  2. int i=1,j=0;
  3. nextval[1]=0;
  4. while(i<strlen(T)){
  5. if(j==0||T[i]==T[j]){
  6. ++i;
  7. ++j;
  8. if(T[i]!=T[j])
  9. nextval[i]=j;
  10. else
  11. nextval[i]=nextval[j];
  12. }
  13. else
  14. j=nextval[j];
  15. }
  16. }

以上为基本算法函数;

以下是完整程序,同时可以展现匹配过程:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include<cstring>
  5. #include<iostream>
  6. using namespace std;
  7. #define OK 1
  8. #define ERROR 0
  9. #define OVERFLOW -2
  10. typedef int Status;
  11. #define MAXSTRLEN 255 //用户可在255以内定义最长串长
  12. typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度
  13. Status StrAssign(SString T, char *chars) { //生成一个其值等于chars的串T
  14. int i;
  15. if (strlen(chars) > MAXSTRLEN)
  16. return ERROR;
  17. else {
  18. T[0] = strlen(chars);
  19. for (i = 1; i <= T[0]; i++)
  20. T[i] = *(chars + i - 1);
  21. return OK;
  22. }
  23. }
  24. void get_next(SString T, int next[]){ //求模式串T的next函数值并存入数组next
  25. int i = 1, j = 0;
  26. next[1] = 0;
  27. while (i < T[0])
  28. if (j == 0 || T[i] == T[j])
  29. {
  30. ++i;
  31. ++j;
  32. next[i] = j;
  33. }//abssgaaadaaaadcf aaaad 0
  34. else
  35. j = next[j];
  36. for(i=1;i<strlen(T);i++)
  37. printf("j=%d next[%d]=%d \n",i,i,next[i]);//abssgaaadaaaadcf aaaad 0
  38. }//get_next
  39. void get_nextval(SString T, int nextval[]){ // 求模式串T的next函数修正值并存入数组nextval
  40. int i = 1, j = 0;
  41. nextval[1] = 0;
  42. while (i < T[0])
  43. if (j == 0 || T[i] == T[j])
  44. {
  45. ++i;
  46. ++j;
  47. if (T[i] != T[j])
  48. nextval[i] = j;
  49. else
  50. nextval[i] = nextval[j];
  51. } else
  52. j = nextval[j];
  53. for(i=1;i<strlen(T);i++)
  54. printf("j=%d nextval[%d]=%d \n",i,i,nextval[i]);
  55. }//get_nextval
  56. //
  57. void BF(char s[100],char p[50],int t){
  58. int space,a,b,k=0,num=0;
  59. int pos, i, j, flag;
  60. j = flag = 0;
  61. if(strlen(s)<strlen(p)){
  62. printf("Error:子串长度大于父串.\n");
  63. return ;
  64. }
  65. if(strlen(s)-strlen(p)<t){
  66. printf("Error:匹配位置不合适.\n");
  67. return ;
  68. }
  69. space=i=pos=t;
  70. printf("\n");
  71. while(i < strlen(s))
  72. {
  73. if(j==0&&s[i]!=p[j])
  74. num++;
  75. pos=i;
  76. if(p[j] == s[i]){
  77. while(j < strlen(p))
  78. {
  79. if(p[j] != s[i])
  80. {
  81. k++;
  82. printf("%s %d 此次匹配失败\n",s,k);
  83. for(a=space;a>0;a--)
  84. printf(" ");//输出详细过程
  85. for(b=0;b<=j;b++)
  86. printf("%c",p[b]);//aaadddawawdcw awd 0
  87. printf("\n");
  88. break;
  89. }
  90. else{
  91. k++;
  92. printf("%s %d 此次匹配成功\n",s,k);
  93. for(a=space;a>0;a--)
  94. printf(" ");//输出详细过程
  95. for(b=0;b<=j;b++)
  96. printf("%c",p[b]);
  97. printf("\n");
  98. i++;
  99. j++;
  100. }
  101. }
  102. if(j == strlen(p))
  103. flag = 1;
  104. }
  105. else{
  106. k++;
  107. printf("%s %d 此次匹配失败\n",s,k);//aaadddawawdcw awd 0
  108. for(a=space;a>0;a--)
  109. printf(" ");
  110. printf("%c\n",p[j]) ;
  111. }
  112. space++;
  113. if(flag == 1){//如果匹配成功,flag=1,则进入此句;
  114. printf("匹配位置为:%d\n", pos);
  115. break;
  116. }
  117. //开始下一轮的循环,对某些变量进行初始化
  118. i = ++pos;
  119. j = 0;
  120. if(i > strlen(s) - strlen(p)){
  121. printf("主串中不存在此子串!\n");
  122. break;
  123. }
  124. }
  125. printf("共匹配%d次\n",k);
  126. printf("单个字符匹配次数为%d\n",num);
  127. }
  128. int KMP(SString S, SString T, char* s, char* p, int pos, int next[]){ // 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
  129. //其中,T非空,1≤pos≤StrLength(S)
  130. if(strlen(s)<strlen(p)){
  131. printf("Error:子串长度大于父串.\n");
  132. return -1;
  133. }
  134. if(strlen(s)-strlen(p)<pos){
  135. printf("Error:匹配位置不合适.\n");
  136. return -1;
  137. }
  138. int i = pos, j = 1,k=0,a,b,space=0;
  139. while (i <= S[0] && j <= T[0])
  140. {
  141. if (j == 0 || S[i] == T[j]) // 继续比较后继字
  142. {
  143. i++;
  144. j++;
  145. if(j == strlen(T))
  146. { // 进入此if语句即表示匹配成功
  147. printf("共循环%d次\n",k);
  148. break;
  149. }
  150. ++k;
  151. printf("%s %d next[%d]=%d \n",s,k,j,next[j]);
  152. for(a=space;a>0;a--)
  153. printf(" ");
  154. for(b=1;b<=j;b++)
  155. printf("%c",T[b]);//abssgaaadaaaadcf aaaad 0
  156. printf("\n");
  157. if(j==1&&S[i]!=T[j]) simple++;//记录单字符匹配失败的次数。
  158. }
  159. else j = next[j];// 模式串向右移动
  160. space=i-j; //输出子串前面的空格数
  161. }
  162. printf("单字符循环%d次\n",simple);
  163. if (j > T[0]) // 匹配成功
  164. return i - T[0];
  165. else
  166. return -1;
  167. }//Index_KMP
  168. int main(){
  169. printf("1.输入主串、子串和匹配起始位置\n2.BF算法\n3.KMP算法\n4.KMP改进算法\n0.退出\n");
  170. int t = -1,place;
  171. SString S;//abssgaaadaaaadcf aaaad 0
  172. SString T;
  173. int *next,*nextval;
  174. char s[50], p[50];
  175. while(t)
  176. {
  177. printf("请输入:");
  178. scanf("%d",&t);
  179. switch(t)
  180. {
  181. case 0:
  182. break;
  183. case 1:
  184. printf("请输入主串、子串和匹配起始位置:\n");
  185. scanf("%s%s%d",s,p,&place);
  186. StrAssign(S,s) ;
  187. StrAssign(T,p) ;
  188. break;
  189. case 2:
  190. BF(s,p,place);
  191. break;
  192. case 3:
  193. next = new int[T[0]+1];
  194. get_next(T,next);
  195. printf("匹配的位置为 %d\n",KMP(S,T,s,p,place,next));
  196. break;
  197. case 4:
  198. nextval = new int[T[0]+1];
  199. get_nextval(T,nextval) ;
  200. printf("匹配的位置为 %d\n",KMP(S,T,s,p,place,nextval));
  201. break;
  202. default:
  203. break;
  204. }
  205. }
  206. return 0;
  207. }

二.字符串替换算法

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. char* str_replace(char* str,char* oldstr,char* newstr){
  5. char bstr[strlen(str)];//转换缓冲区
  6. memset(bstr,0,sizeof(bstr));
  7. for(int i=0; i<strlen(str); i++){
  8. if(!strncmp(str+i,oldstr,strlen(oldstr))){//查找目标字符串
  9. strcat(bstr,newstr);
  10. i = i + strlen(oldstr) - 1;
  11. }else{
  12. strncat(bstr,str+i,1);//保存一字节进缓冲区
  13. }
  14. }
  15. char tmp[strlen(str)*2];
  16. strcpy(tmp,bstr);
  17. return tmp;
  18. }

c语言KMP匹配算法与字符串替换算法的更多相关文章

  1. 搞定KMP匹配算法

    KMP算法介绍及实现——轻松搞定KMP匹配算法 本文介绍了字符串匹配算法中的BF算法和KMP算法.本文中KMP算法介绍部分是关于KMP算法相关文章中最简洁的一篇文章之一.下一篇将继续介绍Horspoo ...

  2. 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版

    课本源码部分 第4章  串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...

  3. iOS开发系列--C语言之数组和字符串

    概览 数组在C语言中有着特殊的地位,它有很多特性,例如它的存储是连续的,数组的名称就是数组的地址等.而在C语言中是没有String类型的,那么如果要表示一个字符串,就必须使用字符数组.今天主要就介绍如 ...

  4. Swift3.0语言教程使用URL字符串

    Swift3.0语言教程使用URL字符串 Swift3.0语言教程使用URL字符串,和路径一样,URL其实也是字符串,我们可以将这些字符串称为URL字符串.本小节将讲解URL字符串的使用. 1.编码 ...

  5. Swift3.0语言教程使用路径字符串

    Swift3.0语言教程使用路径字符串 Swift3.0语言教程使用路径字符串,路径其实是字符串的一种,我们称为路径字符串.本小节将讲解如何使用路径字符串. 1.组合路径 开发者可以将数组快速的组合成 ...

  6. Swift3.0语言教程替换子字符串

    Swift3.0语言教程替换子字符串 Swift3.0语言教程替换子字符串,替换子字符串其实就是将字符串中的子字符串删除,然后再进行添加.为了让这一繁琐的过程变的简单,NSString提供了替换子字符 ...

  7. Swift3.0语言教程获取C字符串

    Swift3.0语言教程获取C字符串 Swift3.0语言教程获取C字符串,为了让Swift和C语言可以实现很好的交互,开发者可以使用NSString的cString(using:)方法在指定编码格式 ...

  8. c语言字符数组与字符串的使用详解

    转自:http://www.jb51.net/article/37456.htm 1.字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素.char str[10]={ ...

  9. C语言多种方法求解字符串编辑距离问题的代码

    把做工程过程经常用的内容记录起来,如下内容段是关于C语言多种方法求解字符串编辑距离问题的内容. { if(xbeg > xend) { if(ybeg > yend) return 0; ...

随机推荐

  1. Apache DolphinScheduler 项目笔记 — 1. 问题定位和排查问题

    导语: Yuanhao Ji 同学是<暑期 2021 - API 模块 UT 测试问题解决>项目负责人,本文记录了他是如何排查和定位问题. 1. 背景 问题:在部分 UT 中使用 Powe ...

  2. 化整为零优化重用,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang函数的定义和使用EP07

    函数是基于功能或者逻辑进行聚合的可复用的代码块.将一些复杂的.冗长的代码抽离封装成多个代码片段,即函数,有助于提高代码逻辑的可读性和可维护性.不同于Python,由于 Go lang是编译型语言,编译 ...

  3. BZOJ1176 [Balkan2007]Mokia(CDQ)

    CDQ裸题,\(x\), \(y\), \(tim\)三维偏序 #include <cstdio> #include <iostream> #include <cstri ...

  4. Spring源码 15 IOC refresh方法10

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  5. Python自动化之常用模块学习

    自动化常用模块 urllib和request模块学习笔记 '获取页面,UI自动化校验页面展示作用': #-*- coding : utf-8 -*-import urllib.requestimpor ...

  6. HMS Core Discovery第17期直播预告|音随我动,秒变音色造型师

    [导读] 随着音视频内容品类的不断丰富及音乐创作门槛不断降低,大量用户正热切的参与到全民创作的大潮中.我们应该怎么去拥抱移动端影音潜力市场?音频编辑又可以有什么新玩法? 本期直播<音随我动,秒变 ...

  7. OpenCV CMake VSCode Windows 平台下运行配置及其解决方案

    前言 最近在搞 计算机图形学相关的东西,有个 demo 用到了 opencv,找了 google 一圈,发现国内都没有比较好的配置和解决的办法,要不就是几年前的教程,最近正好踩坑完,其中经历了自己编译 ...

  8. 万物皆可集成系列:低代码释放用友U8+深度价值(2)—数据拓展应用

    在上一篇内容我们介绍了如何利用低代码开发套件实现低代码应用与U8+系统的对接集成,本次给大家带来的是如何将用友U8+系统中的数据进行价值扩展和实际应用. 我们以生产物料齐套分析为例来说明如何利用低代码 ...

  9. 【MySQL】从入门到掌握2-下载安装

    上期:[MySQL]从入门到掌握1-一些背景知识 第一章:下载 官网下载地址: https://dev.mysql.com/downloads/mysql/ https://dev.mysql.com ...

  10. c# 异步进阶————channel [一]

    前言 该系列为异步编程的进阶篇,其实也不能这么讲.世界上本没有进阶篇,只能说是高级篇(高级篇不能说多高级,是对底层的封装的意思),只要是加深理解都是进阶. 本章先介绍一下channel. 正文 下面没 ...