串这种数据结构,使用是比较多的,但是它的一些方法在更高级的语言中,比如Java,Python中封装的比较完整了。在这里,我只写了串中使用最多的匹配算法,即串的定位操作。串的匹配算法常用的两种就是朴素匹配算法和KMP匹配算法。代码亲测,可直接执行。

  1. #include<stdio.h>
  2.  
  3. /*字符串长度*/
  4. int StringLength(char *L)
  5. {
  6. int i = ; //记录位置
  7. int count = ; //计数器,记录长度
  8. while(L[i]) //判断当前位置是否为空
  9. {
  10. count++; //长度加1
  11. i++; //计数器加1
  12. }
  13. return count; //返回长度
  14. }
  15.  
  16. /*朴素匹配算法*/
  17. int Index(char *S, char *T) //S为主串,T为子串
  18. {
  19. int Slength = StringLength(S); //获得主串S的长度
  20. int Tlength = StringLength(T); //获得子串T的长度
  21. int i = ; //记录主串S当前位置
  22. int j = ; //记录子串T当前位置
  23. // int count = 0;
  24. printf("朴素匹配算法中j回溯的值为:");
  25. while(i < Slength && j < Tlength) //确保两个字符串的当前位置均小于其长度
  26. {
  27. // printf("%d ", j);
  28. // count++;
  29. if(S[i] == T[j]) //判断主串S当前位置与子串T当前位置的字符是否相等
  30. {
  31. i++; //主串S的当前位置加1(后移)
  32. j++; //子串T的当前位置加1(后移)
  33. }
  34. else //如果两字符串的当前位置字符不等
  35. {
  36. i = i - j + ; //主串S的当前位置i回溯到j==0时i位置的下一位置
  37. j = ; //子串T的当前位置j归0
  38. }
  39. }
  40. // printf("\nj共变化了%d次\n", count);
  41. //循环比较完毕
  42. if(j == Tlength) //判断位置j的数值是否与子串T的长度相等
  43. return i - Tlength; //若是,说明搜索成功,返回T在S中出现的首位置
  44. else
  45. return -; //若不是,说明T不存在与S中,返回-1
  46. }
  47.  
  48. /*KMP算法*/
  49. void Get_Next(char *T, int next[])
  50. {
  51. int Tlength = StringLength(T); //获得字符串T的长度
  52. int i = ; //T的后缀位置
  53. int j = -; //T的前缀位置
  54. next[] = -; //next数组的首位赋值为-1
  55. while(i < Tlength) //确保后缀位置小于串长
  56. {
  57. if(j == - || T[i] == T[j]) //如果j==-1,说明前缀已经回退到最前方
  58. { //如果T[i] == T[j],说明当前前缀与后缀相等
  59. i++; //则后缀位置后移一位
  60. j++; //前缀位置后移一位
  61. next[i] = j; //当前后缀位置的next值为j
  62. }
  63. else
  64. j = next[j]; //否则,j回退(还没完全搞懂回退到哪)
  65. }
  66. }
  67.  
  68. int Index_KMP(char *S, char *T)
  69. {
  70. int Slength = StringLength(S); //获得主串S的长度
  71. int Tlength = StringLength(T); //获得子串T的长度
  72. int i = ; //记录S的当前位置
  73. int j = ; //记录T的当前位置
  74. int next[]; //next数组
  75. Get_Next(T, next); //调用Get_Next函数,为next赋值
  76. int count = ;
  77. // printf("KMP算法中j回溯的值为:");
  78. while(i < Slength && j < Tlength)
  79. {
  80. // printf("%d ", j);
  81. // count++;
  82. if(j == - || S[i] == T[j]) //如果j==-1,说明前缀已经回退到最前方
  83. { //如果S[i] == T[j],说明主串与子串当前位置字符相等
  84. i++; //S的当前位置后移一位
  85. j++; //T的当前位置后移一位
  86. }
  87. else
  88. {
  89. j = next[j]; //否则,j回退(未弄懂回退到哪)
  90. }
  91. }
  92. // printf("\nj共变化了%d次\n", count);
  93. if(j == Tlength) //比较结束,判断j的值是否与T的长度相等
  94. return i - Tlength; //若是,返回T在S中出现的开始位置
  95. else
  96. return -; //若不是,返回-1
  97. }
  98.  
  99. /*KMP改进版算法*/
  100. void Get_Next_Val(char *T, int nextVal[])
  101. {
  102. int Tlength = StringLength(T); //获得子串T的长度
  103. int i = ; //记录后缀位置
  104. int j = -; //记录前缀位置
  105. nextVal[] = -; //next数组第一位置赋值为-1
  106. while(i < Tlength)
  107. {
  108. if(j == - || T[i] == T[j]) //同上
  109. {
  110. i++; //同上
  111. j++;
  112. if(T[i] != T[j]) //如果位置后移一位后的值不相等
  113. nextVal[i] = j; //nextVal等于j
  114. else //如果相等
  115. nextVal[i] = nextVal[j]; //当前后缀位置的nextVal值等于j位置的nextVal的值
  116. }
  117. else
  118. j = nextVal[j]; //同上
  119. }
  120. }
  121.  
  122. int Index_KMP_Val(char *S, char *T)
  123. {
  124. int Slength = StringLength(S); //获得主串S的长度
  125. int Tlength = StringLength(T); //获得子串T的长度
  126. int i = ; //记录S的当前位置
  127. int j = ; //记录T的当前位置
  128. int next[]; //next数组
  129. Get_Next_Val(T, next); //调用Get_Next函数,为next赋值
  130. int count = ;
  131. printf("KMP_Val算法中j回溯的值为:");
  132. while(i < Slength && j < Tlength)
  133. {
  134. printf("%d ", j);
  135. count++;
  136. if(j == - || S[i] == T[j]) //如果j==-1,说明前缀已经回退到最前方
  137. { //如果S[i] == T[j],说明主串与子串当前位置字符相等
  138. i++; //S的当前位置后移一位
  139. j++; //T的当前位置后移一位
  140. }
  141. else
  142. {
  143. j = next[j]; //否则,j回退(未弄懂回退到哪)
  144. }
  145. }
  146. printf("\nj共变化了%d次\n", count);
  147. if(j == Tlength) //比较结束,判断j的值是否与T的长度相等
  148. return i - Tlength; //若是,返回T在S中出现的开始位置
  149. else
  150. return -; //若不是,返回-1
  151. }
  152.  
  153. void main()
  154. {
  155. char *S = "aaaaaaaaaaaaaaaaaaaaabcde";
  156. char *T = "aaaaaaaaaaaaaaaaaaaaaaaax";
  157. int pos;
  158. pos = Index(S, T);
  159. if(pos != -)
  160. printf("朴素匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos);
  161. else
  162. printf("朴素匹配算法:子串T不存在与主串S中\n");
  163. printf("---------------------------------------------------------------------\n");
  164. int pos_KMP;
  165. pos_KMP = Index_KMP(S, T);
  166. if(pos_KMP != -)
  167. printf("KMP匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos_KMP);
  168. else
  169. printf("KMP匹配算法:子串T不存在与主串S中\n");
  170. printf("---------------------------------------------------------------------\n");
  171. int pos_KMP_val;
  172. pos_KMP_val = Index_KMP_Val(S, T);
  173. if(pos_KMP_val != -)
  174. printf("KMP_Val匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos_KMP_val);
  175. else
  176. printf("KMP_Val匹配算法:子串T不存在与主串S中\n");
  177. }

串的匹配算法--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. if __name__ == "__main__" 的作用

    作用:当模块被直接运行时,以下代码块将被运行,当模块是被导入时,代码块不被运行. 例子: # file one.py def func(): print("func() in one.py& ...

  2. 《吊打面试官》系列-Redis终章_凛冬将至、FPX_新王登基

    你知道的越多,你不知道的越多 点赞再看,养成习惯 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难.作为一个在互联 ...

  3. 只需十四步:从零开始掌握Python机器学习(附资源)

    转载:只需十四步:从零开始掌握Python机器学习(附资源) Python 可以说是现在最流行的机器学习语言,而且你也能在网上找到大量的资源.你现在也在考虑从 Python 入门机器学习吗?本教程或许 ...

  4. dhcpv6+radvd服务器搭建

    1.isc-dhcp-server install sudo apt update sudo apt-get install isc-dhcp-server 2.设置dhcp 创建/etc/dhcp/ ...

  5. 2019年10月11号 王庆超 linux

    1.计算机操作系统简介 (1)掌握操作系统的定义:操作系统是一个用来协调.管理和控制计算机硬件和软件资源的系统 程序,它位于硬件和应用程序之间. (2)掌握操作系统的内核的定义:操作系统的内核是一个管 ...

  6. PHP获取PHP执行的时间

    php获取PHP执行的时间 <pre> //程序运行时间 $starttime = explode(' ',microtime()); //代码区域 //程序运行时间 $endtime = ...

  7. Python面向对象 | 类的成员

    一. 细分类的组成成员 之前咱们讲过类大致分两块区域,静态字段部分和方法部分. 每个区域详细划分又可以分为: class A: company = '阿里巴巴' # 静态变量(静态字段) __tel ...

  8. 淘宝小练习#css

    * { margin: 0; padding: 0; } a { text-decoration: none; } .box { background: #f4f4f4; } /* 头部样式STAR ...

  9. 配置SElinux环境,将SELinux设置为enforcing

    SELinux是 美国国家安全局 (NSA) 对于 强制访问控制的实现 =>可以使root受限的权限 关闭SELinux=>修改配置文件,永久生效; sed -i 's/SELINUX=e ...

  10. PHP 修改数组中的值

    PHP 修改数组中的值 ①.二维数组可以通过 for($i = 0; $i < count(Array()); ++ $i) 这种形式修改 实例代码: // 修改 二维数组中的 name为 Ge ...