串这种数据结构,使用是比较多的,但是它的一些方法在更高级的语言中,比如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语言实现的更多相关文章

  1. BF算法(串模式匹配算法)

    主串和子串 主串与子串:如果串 A(如 "shujujiegou")中包含有串 B(如 "ju"),则称串 A 为主串,串 B 为子串.主串与子串之间的关系可简 ...

  2. SHA算法:签名串SHA算法Java语言参考(SHAHelper.java)

    SHAHelper.java package com.util; /** * @author wangxiangyu * @date:2017年10月16日 上午9:00:47 * 类说明:SHA签名 ...

  3. UTF-8, Unicode, GB2312格式串转换之C语言版

    原住址:http://www.cnitblog.com/wujian-IT/archive/2007/12/13/37671.html           /*      author:   wu.j ...

  4. 7、UTF-8, Unicode, GB2312格式串转换之C语言版

    (申明:此文章属于原创,若转载请表明作者和原处链接 )            /*      author:   wu.jian    (吴剑)      English name: Sword    ...

  5. 括号匹配算法 C语言实现

    #include <stdio.h> #include <malloc.h> //malloc,realloc #include <math.h> //含有over ...

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

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

  7. 串、KMP模式匹配算法

    串是由0个或者多个字符组成的有限序列,又名叫字符串. 串的比较: 串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号. 计算机中常用的ASCII编码,由8位二进制 ...

  8. 数据结构(c语言版)代码

    第1章  绪论       文档中源码及测试数据存放目录:数据结构\▲课本算法实现\▲01 绪论  概述        第一章作为绪论,主要介绍了数据结构与算法中的一些基本概念和术语.对于这些概念术语 ...

  9. KOTLIN开发语言文档(官方文档) -- 2.基本概念

    网页链接:https://kotlinlang.org/docs/reference/basic-types.html 2.   基本概念 2.1.  基本类型 从可以在任何变量处理调用成员函数和属性 ...

随机推荐

  1. 敏捷宣言(Agile Manifesto)和敏捷开发十二原则

    敏捷宣言 The Agile Manifesto Individuals and interactions over Process and tools 个体与交互 重于 过程和工具 Working ...

  2. Flex简记

    display的flex属性的使用对象分为1.容器即包含有元素的元素,2.项目,即某一个元素.就容器而言,flex可以实现换行(flex-wrap),改变容器内元素的排列方向(flex-directi ...

  3. Matplotlib 中常见的图形

    # 导包 from matplotlib import pyplot as plt import numpy as np 线性图 简单线性图 在图表的所有类型中,线性图最为简单.线性图的各个数据点由一 ...

  4. 卡特兰数&&prufer序列&&BSGS水题集

    首先说一下BSGS的一个坑点: 解方程A^x≡B(mod p) 需要特判一个东西=>A%p==B%p==0? 如果相等的话puts("1")反之则无解. 因为如果A%p=0, ...

  5. P5304旅行者(比bk201还要流氓的解法)

    题目如上. 暴力碾标算,n^2过百万!! 作为一道黑题它确实有点点水(如果是畜生解法的话) 就是找出两两点之间的最短路的最小值. 本来是很高深的一题,要跑两遍最短路啊,然后染色啊,再拓展什么的,但是! ...

  6. JVM初体验

    一.设计堆内存溢出异常:OutOfMemoryError: public class Main { public static void main(String[] args) { List<D ...

  7. VM小技巧——虚拟机解决vm窗口太小的办法

    ——" 慢下来总结才能增大效率" 很多人在装虚拟机的时候,遇到了窗口过小不能自适应的问题.我也是查了好多资料,都说安装Vmware Tools即可解决,还有说修改分辨率也可以.两种 ...

  8. 利用python实现微信小程序游戏跳一跳详细教程

    利用python实现微信小程序游戏跳一跳详细教程 1 先安装python 然后再安装pip <a href="http://newmiracle.cn/wp-content/uploa ...

  9. 基于docker搭建Jenkins+Gitlab+Harbor+Rancher架构实现CI/CD操作

    一.各个组件的功能描述: Docker 是一个开源的应用容器引擎. Jenkis 是一个开源自动化服务器. (1).负责监控gitlab代码.gitlab中配置文件的变动: (2).负责执行镜像文件的 ...

  10. mysql双主互为主从配置

    在使用双主互为主从的模式前提是互为主从的两个数据库,表的主键必须是自增的. 环境不多说了 ,多台mysql单实例或单台多实例都可以.多实例的配置请参考:https://www.cnblogs.com/ ...