c语言KMP匹配算法与字符串替换算法
一.字符串匹配算法
(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匹配算法与字符串替换算法的更多相关文章
- 搞定KMP匹配算法
KMP算法介绍及实现——轻松搞定KMP匹配算法 本文介绍了字符串匹配算法中的BF算法和KMP算法.本文中KMP算法介绍部分是关于KMP算法相关文章中最简洁的一篇文章之一.下一篇将继续介绍Horspoo ...
- 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
课本源码部分 第4章 串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版 源码使用说明 链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...
- iOS开发系列--C语言之数组和字符串
概览 数组在C语言中有着特殊的地位,它有很多特性,例如它的存储是连续的,数组的名称就是数组的地址等.而在C语言中是没有String类型的,那么如果要表示一个字符串,就必须使用字符数组.今天主要就介绍如 ...
- Swift3.0语言教程使用URL字符串
Swift3.0语言教程使用URL字符串 Swift3.0语言教程使用URL字符串,和路径一样,URL其实也是字符串,我们可以将这些字符串称为URL字符串.本小节将讲解URL字符串的使用. 1.编码 ...
- Swift3.0语言教程使用路径字符串
Swift3.0语言教程使用路径字符串 Swift3.0语言教程使用路径字符串,路径其实是字符串的一种,我们称为路径字符串.本小节将讲解如何使用路径字符串. 1.组合路径 开发者可以将数组快速的组合成 ...
- Swift3.0语言教程替换子字符串
Swift3.0语言教程替换子字符串 Swift3.0语言教程替换子字符串,替换子字符串其实就是将字符串中的子字符串删除,然后再进行添加.为了让这一繁琐的过程变的简单,NSString提供了替换子字符 ...
- Swift3.0语言教程获取C字符串
Swift3.0语言教程获取C字符串 Swift3.0语言教程获取C字符串,为了让Swift和C语言可以实现很好的交互,开发者可以使用NSString的cString(using:)方法在指定编码格式 ...
- c语言字符数组与字符串的使用详解
转自:http://www.jb51.net/article/37456.htm 1.字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素.char str[10]={ ...
- C语言多种方法求解字符串编辑距离问题的代码
把做工程过程经常用的内容记录起来,如下内容段是关于C语言多种方法求解字符串编辑距离问题的内容. { if(xbeg > xend) { if(ybeg > yend) return 0; ...
随机推荐
- 手把手教你定位线上MySQL锁超时问题,包教包会
昨晚我正在床上睡得着着的,突然来了一条短信. 什么?线上的订单无法取消! 我赶紧登录线上系统,查看业务日志. 发现有MySQL锁超时的错误日志. 不用想,肯定有另一个事务正在修改这条订单,持有这条订单 ...
- 应用集成-在Hexo、Hugo博客框架中使用Gitalk基于Github上仓库项目的issue无后端服务评论系统实践
关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 0x00 Gi ...
- 我开源了一个Go学习仓库|笔记预览
前言 大半个月前我参与了字节后端面试,未通过第四面,面试总结写在了这篇文章: https://juejin.cn/post/7132712873351970823 在此文的末尾,我写到为了全面回顾Go ...
- 持久化-Powershell配置文件持久性
持久化-Powershell配置文件持久性 概述 可以使用Powershell配置文件进行持久性和/或特权升级. 执行 获取可以滥用的powershell配置文件,这取决于你拥有的权限. $PROFI ...
- 【MySQL】从入门到掌握4-主键与Unique
上期:[MySQL]从入门到掌握3-WorkBench 第一章:主键 在实际开发中,我们不会使用用户名字当作主键. 因为当我们用数据库记录学生信息的时候,学生有可能重名! 我们一般会使用是个int ...
- Spring5事务管理
事务管理是什么? 相当于过滤器,如果这一进程中上一个操作正常执行完后提交数据已经发生改变,但是下一个操作中出现了异常,这样就会影响数据的查看. 典型例子:银行转账,甲方已经转钱给乙方(甲方已扣钱),乙 ...
- Kingbase V8R6集群安装部署案例---脚本在线一键扩容
案例说明: KingbaseES V8R6支持图形化方式在线扩容,但是在一些生产环境,在服务器不支持图形化界面的情况下 ,只能通过脚本命令行的方式执行集群的部署或在线扩容. Tips: Kingbas ...
- Mysql 实现 向上递归查找父节点并返回树结构
需求:通过mysql 8.0以下版本实现,一个人多角色id,一个角色对应某个节点menu_id,根节点的父节点存储为NULL, 向上递归查找父节点并返回树结构. 如果只有叶子,剔除掉; 如果只有根,只 ...
- Docker安装MySQL并使用Navicat连接
MySQL简单介绍: MySQL 是一个开放源码的关系数据库管理系统,开发者为瑞典 MySQL AB 公司.目前 MySQL 被广泛地应用在 Internet 上的大中小型网站中.由于其体积小.速度快 ...
- Java中的Optional
在我们日常的开发中,我们经常会遇到 NullPointerException.如何才能优雅的处理NPE?这里告诉大家一个较为流行的方法 java.util.Optional 使用Optional来修饰 ...