串的匹配算法--C语言实现
串这种数据结构,使用是比较多的,但是它的一些方法在更高级的语言中,比如Java,Python中封装的比较完整了。在这里,我只写了串中使用最多的匹配算法,即串的定位操作。串的匹配算法常用的两种就是朴素匹配算法和KMP匹配算法。代码亲测,可直接执行。
#include<stdio.h> /*字符串长度*/
int StringLength(char *L)
{
int i = ; //记录位置
int count = ; //计数器,记录长度
while(L[i]) //判断当前位置是否为空
{
count++; //长度加1
i++; //计数器加1
}
return count; //返回长度
} /*朴素匹配算法*/
int Index(char *S, char *T) //S为主串,T为子串
{
int Slength = StringLength(S); //获得主串S的长度
int Tlength = StringLength(T); //获得子串T的长度
int i = ; //记录主串S当前位置
int j = ; //记录子串T当前位置
// int count = 0;
printf("朴素匹配算法中j回溯的值为:");
while(i < Slength && j < Tlength) //确保两个字符串的当前位置均小于其长度
{
// printf("%d ", j);
// count++;
if(S[i] == T[j]) //判断主串S当前位置与子串T当前位置的字符是否相等
{
i++; //主串S的当前位置加1(后移)
j++; //子串T的当前位置加1(后移)
}
else //如果两字符串的当前位置字符不等
{
i = i - j + ; //主串S的当前位置i回溯到j==0时i位置的下一位置
j = ; //子串T的当前位置j归0
}
}
// printf("\nj共变化了%d次\n", count);
//循环比较完毕
if(j == Tlength) //判断位置j的数值是否与子串T的长度相等
return i - Tlength; //若是,说明搜索成功,返回T在S中出现的首位置
else
return -; //若不是,说明T不存在与S中,返回-1
} /*KMP算法*/
void Get_Next(char *T, int next[])
{
int Tlength = StringLength(T); //获得字符串T的长度
int i = ; //T的后缀位置
int j = -; //T的前缀位置
next[] = -; //next数组的首位赋值为-1
while(i < Tlength) //确保后缀位置小于串长
{
if(j == - || T[i] == T[j]) //如果j==-1,说明前缀已经回退到最前方
{ //如果T[i] == T[j],说明当前前缀与后缀相等
i++; //则后缀位置后移一位
j++; //前缀位置后移一位
next[i] = j; //当前后缀位置的next值为j
}
else
j = next[j]; //否则,j回退(还没完全搞懂回退到哪)
}
} int Index_KMP(char *S, char *T)
{
int Slength = StringLength(S); //获得主串S的长度
int Tlength = StringLength(T); //获得子串T的长度
int i = ; //记录S的当前位置
int j = ; //记录T的当前位置
int next[]; //next数组
Get_Next(T, next); //调用Get_Next函数,为next赋值
int count = ;
// printf("KMP算法中j回溯的值为:");
while(i < Slength && j < Tlength)
{
// printf("%d ", j);
// count++;
if(j == - || S[i] == T[j]) //如果j==-1,说明前缀已经回退到最前方
{ //如果S[i] == T[j],说明主串与子串当前位置字符相等
i++; //S的当前位置后移一位
j++; //T的当前位置后移一位
}
else
{
j = next[j]; //否则,j回退(未弄懂回退到哪)
}
}
// printf("\nj共变化了%d次\n", count);
if(j == Tlength) //比较结束,判断j的值是否与T的长度相等
return i - Tlength; //若是,返回T在S中出现的开始位置
else
return -; //若不是,返回-1
} /*KMP改进版算法*/
void Get_Next_Val(char *T, int nextVal[])
{
int Tlength = StringLength(T); //获得子串T的长度
int i = ; //记录后缀位置
int j = -; //记录前缀位置
nextVal[] = -; //next数组第一位置赋值为-1
while(i < Tlength)
{
if(j == - || T[i] == T[j]) //同上
{
i++; //同上
j++;
if(T[i] != T[j]) //如果位置后移一位后的值不相等
nextVal[i] = j; //nextVal等于j
else //如果相等
nextVal[i] = nextVal[j]; //当前后缀位置的nextVal值等于j位置的nextVal的值
}
else
j = nextVal[j]; //同上
}
} int Index_KMP_Val(char *S, char *T)
{
int Slength = StringLength(S); //获得主串S的长度
int Tlength = StringLength(T); //获得子串T的长度
int i = ; //记录S的当前位置
int j = ; //记录T的当前位置
int next[]; //next数组
Get_Next_Val(T, next); //调用Get_Next函数,为next赋值
int count = ;
printf("KMP_Val算法中j回溯的值为:");
while(i < Slength && j < Tlength)
{
printf("%d ", j);
count++;
if(j == - || S[i] == T[j]) //如果j==-1,说明前缀已经回退到最前方
{ //如果S[i] == T[j],说明主串与子串当前位置字符相等
i++; //S的当前位置后移一位
j++; //T的当前位置后移一位
}
else
{
j = next[j]; //否则,j回退(未弄懂回退到哪)
}
}
printf("\nj共变化了%d次\n", count);
if(j == Tlength) //比较结束,判断j的值是否与T的长度相等
return i - Tlength; //若是,返回T在S中出现的开始位置
else
return -; //若不是,返回-1
} void main()
{
char *S = "aaaaaaaaaaaaaaaaaaaaabcde";
char *T = "aaaaaaaaaaaaaaaaaaaaaaaax";
int pos;
pos = Index(S, T);
if(pos != -)
printf("朴素匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos);
else
printf("朴素匹配算法:子串T不存在与主串S中\n");
printf("---------------------------------------------------------------------\n");
int pos_KMP;
pos_KMP = Index_KMP(S, T);
if(pos_KMP != -)
printf("KMP匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos_KMP);
else
printf("KMP匹配算法:子串T不存在与主串S中\n");
printf("---------------------------------------------------------------------\n");
int pos_KMP_val;
pos_KMP_val = Index_KMP_Val(S, T);
if(pos_KMP_val != -)
printf("KMP_Val匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos_KMP_val);
else
printf("KMP_Val匹配算法:子串T不存在与主串S中\n");
}
串的匹配算法--C语言实现的更多相关文章
- BF算法(串模式匹配算法)
主串和子串 主串与子串:如果串 A(如 "shujujiegou")中包含有串 B(如 "ju"),则称串 A 为主串,串 B 为子串.主串与子串之间的关系可简 ...
- SHA算法:签名串SHA算法Java语言参考(SHAHelper.java)
SHAHelper.java package com.util; /** * @author wangxiangyu * @date:2017年10月16日 上午9:00:47 * 类说明:SHA签名 ...
- UTF-8, Unicode, GB2312格式串转换之C语言版
原住址:http://www.cnitblog.com/wujian-IT/archive/2007/12/13/37671.html /* author: wu.j ...
- 7、UTF-8, Unicode, GB2312格式串转换之C语言版
(申明:此文章属于原创,若转载请表明作者和原处链接 ) /* author: wu.jian (吴剑) English name: Sword ...
- 括号匹配算法 C语言实现
#include <stdio.h> #include <malloc.h> //malloc,realloc #include <math.h> //含有over ...
- 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
课本源码部分 第4章 串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版 源码使用说明 链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...
- 串、KMP模式匹配算法
串是由0个或者多个字符组成的有限序列,又名叫字符串. 串的比较: 串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号. 计算机中常用的ASCII编码,由8位二进制 ...
- 数据结构(c语言版)代码
第1章 绪论 文档中源码及测试数据存放目录:数据结构\▲课本算法实现\▲01 绪论 概述 第一章作为绪论,主要介绍了数据结构与算法中的一些基本概念和术语.对于这些概念术语 ...
- KOTLIN开发语言文档(官方文档) -- 2.基本概念
网页链接:https://kotlinlang.org/docs/reference/basic-types.html 2. 基本概念 2.1. 基本类型 从可以在任何变量处理调用成员函数和属性 ...
随机推荐
- 对pwntools生成的exp模版做了一些修改
安装pwntools后,有一些命令行的工具可以用 ~ pwn template -h usage: pwn template [-h] [--host HOST] [--port PORT] [--u ...
- Vue计算属性缓存(computed) vs 方法
Vue计算属性缓存(computed) vs 方法 实例 <div id="example"> <p>Original message: "{{ ...
- 学习笔记 : python 文件操作
1.如果文件路径带有 \ 比如 open('c:\python\test.txt') 会报:SyntaxError: (unicode error) 'unicodeescape' codec ...
- 11、pytest -- 测试的参数化
目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...
- 基于 ThinkPHP5 + Bootstrap 的后台开发框架 FastAdmin
FastAdmin是一款基于 ThinkPHP5 + Bootstrap 的极速后台开发框架. 主要特性 基于Auth验证的权限管理系统 支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及 ...
- 使用.net core中的类DispatchProxy实现AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是软件开发中的一个热点,利用A ...
- jquery 路径动画贝塞尔动画
jquery 路径动画贝塞尔动画 <pre><!DOCTYPE html><!DOCTYPE html><html> <head> < ...
- VS2019打包WPF安装程序最新教程
VS2019打包WPF安装程序最新教程,使用Visual Studio 2019开发的WPF程序如果想要打包为安装程序,除了在VS2019找到WPF项目类库直接右键发布之外,更常用的还是将其打包为ex ...
- Git III: 撤销操作
所谓撤销操作,无非就是后悔药.对Git来说,撤销操作主要是以下几块: 撤销已经提交的Commit. 对已经通过git add加入Stage的文件,进行unstage操作. 对已经是Untracked却 ...
- nyoj 7 街区最短路径问题 (曼哈顿距离(出租车几何) or 暴力)
街区最短路径问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 一个街区有很多住户,街区的街道只能为东西.南北两种方向. 住户只可以沿着街道行走. 各个街道之间的间 ...