一.字符串匹配算法

(1)传统匹配算法BF

int Index_BF(char* S, char* T){
int i=1,j=1;
while(i<=strlen(S) && j<=strlen(T)){
if(S[i]==T[j]){
++i;
++j;
}
else{
i=i-j+2;
j=1;
}
}
if(j>strlen(T))
return i - strlen(T);
else
return 0;
}

(2)KMP

void get_next(char* T, int next[]){
int i=1,j=0;
next[1]=0;
while(i<strlen(T)){
if(j==0||T[i]==T[j]){
++i;
++j;
next[i]=j;
}
else
j=next[j];
}
} int Index_KMP(char* S, char* T, int next[]){
int i=1, j=1;
while (i<=strlen(S)&&j<=strlen(T)){
if(j==0||S[i]==T[j]){
++i;
++j;
}
else
j=next[j];
}
if(j>strlen(T))
return i-strlen(T);
else
return 0;
}

(3)KMP改进算法

void get_nextval(char* T,int nextval[]){
int i=1,j=0;
nextval[1]=0;
while(i<strlen(T)){
if(j==0||T[i]==T[j]){
++i;
++j;
if(T[i]!=T[j])
nextval[i]=j;
else
nextval[i]=nextval[j];
}
else
j=nextval[j];
}
}

以上为基本算法函数;

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include<cstring>
#include<iostream>
using namespace std; #define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度 Status StrAssign(SString T, char *chars) { //生成一个其值等于chars的串T
int i;
if (strlen(chars) > MAXSTRLEN)
return ERROR;
else {
T[0] = strlen(chars);
for (i = 1; i <= T[0]; i++)
T[i] = *(chars + i - 1);
return OK;
}
} void get_next(SString T, int next[]){ //求模式串T的next函数值并存入数组next
int i = 1, j = 0;
next[1] = 0;
while (i < T[0])
if (j == 0 || T[i] == T[j])
{
++i;
++j;
next[i] = j;
}//abssgaaadaaaadcf aaaad 0
else
j = next[j];
for(i=1;i<strlen(T);i++)
printf("j=%d next[%d]=%d \n",i,i,next[i]);//abssgaaadaaaadcf aaaad 0
}//get_next void get_nextval(SString T, int nextval[]){ // 求模式串T的next函数修正值并存入数组nextval
int i = 1, j = 0;
nextval[1] = 0;
while (i < T[0])
if (j == 0 || T[i] == T[j])
{
++i;
++j;
if (T[i] != T[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
} else
j = nextval[j];
for(i=1;i<strlen(T);i++)
printf("j=%d nextval[%d]=%d \n",i,i,nextval[i]);
}//get_nextval
//
void BF(char s[100],char p[50],int t){
int space,a,b,k=0,num=0;
int pos, i, j, flag;
j = flag = 0;
if(strlen(s)<strlen(p)){
printf("Error:子串长度大于父串.\n");
return ;
}
if(strlen(s)-strlen(p)<t){
printf("Error:匹配位置不合适.\n");
return ;
}
space=i=pos=t;
printf("\n");
while(i < strlen(s))
{
if(j==0&&s[i]!=p[j])
num++;
pos=i;
if(p[j] == s[i]){
while(j < strlen(p))
{
if(p[j] != s[i])
{
k++;
printf("%s %d 此次匹配失败\n",s,k);
for(a=space;a>0;a--)
printf(" ");//输出详细过程
for(b=0;b<=j;b++)
printf("%c",p[b]);//aaadddawawdcw awd 0
printf("\n");
break;
}
else{
k++;
printf("%s %d 此次匹配成功\n",s,k);
for(a=space;a>0;a--)
printf(" ");//输出详细过程
for(b=0;b<=j;b++)
printf("%c",p[b]);
printf("\n");
i++;
j++;
}
}
if(j == strlen(p))
flag = 1;
}
else{
k++;
printf("%s %d 此次匹配失败\n",s,k);//aaadddawawdcw awd 0
for(a=space;a>0;a--)
printf(" ");
printf("%c\n",p[j]) ;
}
space++;
if(flag == 1){//如果匹配成功,flag=1,则进入此句;
printf("匹配位置为:%d\n", pos);
break;
}
//开始下一轮的循环,对某些变量进行初始化
i = ++pos;
j = 0;
if(i > strlen(s) - strlen(p)){
printf("主串中不存在此子串!\n");
break;
}
}
printf("共匹配%d次\n",k);
printf("单个字符匹配次数为%d\n",num);
} int KMP(SString S, SString T, char* s, char* p, int pos, int next[]){ // 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
//其中,T非空,1≤pos≤StrLength(S)
if(strlen(s)<strlen(p)){
printf("Error:子串长度大于父串.\n");
return -1;
}
if(strlen(s)-strlen(p)<pos){
printf("Error:匹配位置不合适.\n");
return -1;
}
int i = pos, j = 1,k=0,a,b,space=0;
while (i <= S[0] && j <= T[0])
{
if (j == 0 || S[i] == T[j]) // 继续比较后继字
{
i++;
j++;
if(j == strlen(T))
{ // 进入此if语句即表示匹配成功
printf("共循环%d次\n",k);
break;
} ++k;
printf("%s %d next[%d]=%d \n",s,k,j,next[j]);
for(a=space;a>0;a--)
printf(" ");
for(b=1;b<=j;b++)
printf("%c",T[b]);//abssgaaadaaaadcf aaaad 0
printf("\n");
if(j==1&&S[i]!=T[j]) simple++;//记录单字符匹配失败的次数。
}
else j = next[j];// 模式串向右移动
space=i-j; //输出子串前面的空格数
}
printf("单字符循环%d次\n",simple);
if (j > T[0]) // 匹配成功
return i - T[0];
else
return -1;
}//Index_KMP int main(){
printf("1.输入主串、子串和匹配起始位置\n2.BF算法\n3.KMP算法\n4.KMP改进算法\n0.退出\n");
int t = -1,place;
SString S;//abssgaaadaaaadcf aaaad 0
SString T;
int *next,*nextval;
char s[50], p[50];
while(t)
{
printf("请输入:");
scanf("%d",&t);
switch(t)
{
case 0:
break;
case 1:
printf("请输入主串、子串和匹配起始位置:\n");
scanf("%s%s%d",s,p,&place);
StrAssign(S,s) ;
StrAssign(T,p) ;
break;
case 2:
BF(s,p,place);
break;
case 3:
next = new int[T[0]+1];
get_next(T,next);
printf("匹配的位置为 %d\n",KMP(S,T,s,p,place,next));
break;
case 4:
nextval = new int[T[0]+1];
get_nextval(T,nextval) ;
printf("匹配的位置为 %d\n",KMP(S,T,s,p,place,nextval));
break;
default:
break;
}
}
return 0;
}

二.字符串替换算法

#include<stdio.h>
#include<string.h>
#include<stdlib.h> char* str_replace(char* str,char* oldstr,char* newstr){
char bstr[strlen(str)];//转换缓冲区
memset(bstr,0,sizeof(bstr));
for(int i=0; i<strlen(str); i++){
if(!strncmp(str+i,oldstr,strlen(oldstr))){//查找目标字符串
strcat(bstr,newstr);
i = i + strlen(oldstr) - 1;
}else{
strncat(bstr,str+i,1);//保存一字节进缓冲区
}
}
char tmp[strlen(str)*2];
strcpy(tmp,bstr);
return tmp;
}

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. async...await在tcp通讯中的正确用法

    引言 编程能力在不断的总结中进步以及成长,最近的半年里,对之前的开源项目代码进行回归,在重构的过程中进行了很多思考,很多次都想放弃重构,毕竟一个已经在使用的项目,重构基础代码就相当于重新开发了,不过最 ...

  2. Luogu2073 送花 (平衡树)

    打感叹号处为傻逼处 #include <iostream> #include <cstdio> #include <cstring> #include <al ...

  3. Redis 15 主从复制

    参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 概述 主从复制 ...

  4. jbd2的死锁分析

    已经运行多年的jbd2,它还是死锁了 背景:这个是在centos7的环境上复现的,内核版本为3.10.0-957.27.2.el7 下面列一下我们是怎么排查并解这个问题的. 一.故障现象 oppo云内 ...

  5. [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习)

    [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习) 在C#中,存在常见的九种集合类型:动态数组ArrayList.列表List.排序列表SortedList.哈希表HashTa ...

  6. Vue3中defineEmits、defineProps 是怎么做到不用引入就能直接用的

    最近正在将一个使用单文件组件的 Options API 的 Vue2 JavaScript 项目升级为 Vue3 typescript,并利用 Composition API 的优势. 比如,下面这种 ...

  7. HTML初学者小知识2

    网页内嵌 代码以及演示如下 代码 <div id="tab_1"> <iframe src="div.html" height="5 ...

  8. 截取url后缀扩展名方法

    原本使用 Path(_['video']['downloadUrl']).suffix 获取文件扩展名,没想到出错了,查明原因发现某视频链接是https://xx.xxx.xxx/xx/xxxx.mp ...

  9. KingbaseES不同字符类型比较转换规则

    Postgresql 常用的字符数据类型的有char.varchar和text,其中 char 固定长度类型, varchar 和 text 是可变长度类型.这三种类型在进行比较时,会进行隐含的类型转 ...

  10. 《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(18)-Fiddler如何接口测试,妈妈再也不担心我不会接口测试了

    1.简介 Fiddler最大的优势在于抓包,我们大部分使用的功能也在抓包的功能上,fiddler做接口测试也是非常方便的. 领导或者开发给你安排接口测试的工作任务,但是没有给你接口文档(由于开发周期没 ...