串的匹配算法--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. 基本类型 从可以在任何变量处理调用成员函数和属性 ...
随机推荐
- 敏捷宣言(Agile Manifesto)和敏捷开发十二原则
敏捷宣言 The Agile Manifesto Individuals and interactions over Process and tools 个体与交互 重于 过程和工具 Working ...
- Flex简记
display的flex属性的使用对象分为1.容器即包含有元素的元素,2.项目,即某一个元素.就容器而言,flex可以实现换行(flex-wrap),改变容器内元素的排列方向(flex-directi ...
- Matplotlib 中常见的图形
# 导包 from matplotlib import pyplot as plt import numpy as np 线性图 简单线性图 在图表的所有类型中,线性图最为简单.线性图的各个数据点由一 ...
- 卡特兰数&&prufer序列&&BSGS水题集
首先说一下BSGS的一个坑点: 解方程A^x≡B(mod p) 需要特判一个东西=>A%p==B%p==0? 如果相等的话puts("1")反之则无解. 因为如果A%p=0, ...
- P5304旅行者(比bk201还要流氓的解法)
题目如上. 暴力碾标算,n^2过百万!! 作为一道黑题它确实有点点水(如果是畜生解法的话) 就是找出两两点之间的最短路的最小值. 本来是很高深的一题,要跑两遍最短路啊,然后染色啊,再拓展什么的,但是! ...
- JVM初体验
一.设计堆内存溢出异常:OutOfMemoryError: public class Main { public static void main(String[] args) { List<D ...
- VM小技巧——虚拟机解决vm窗口太小的办法
——" 慢下来总结才能增大效率" 很多人在装虚拟机的时候,遇到了窗口过小不能自适应的问题.我也是查了好多资料,都说安装Vmware Tools即可解决,还有说修改分辨率也可以.两种 ...
- 利用python实现微信小程序游戏跳一跳详细教程
利用python实现微信小程序游戏跳一跳详细教程 1 先安装python 然后再安装pip <a href="http://newmiracle.cn/wp-content/uploa ...
- 基于docker搭建Jenkins+Gitlab+Harbor+Rancher架构实现CI/CD操作
一.各个组件的功能描述: Docker 是一个开源的应用容器引擎. Jenkis 是一个开源自动化服务器. (1).负责监控gitlab代码.gitlab中配置文件的变动: (2).负责执行镜像文件的 ...
- mysql双主互为主从配置
在使用双主互为主从的模式前提是互为主从的两个数据库,表的主键必须是自增的. 环境不多说了 ,多台mysql单实例或单台多实例都可以.多实例的配置请参考:https://www.cnblogs.com/ ...