串的匹配算法--C语言实现

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

  1 #include<stdio.h>
  2
  3 /*字符串长度*/
  4 int StringLength(char *L)
  5 {
  6     int i = 0;                //记录位置
  7     int count = 0;            //计数器,记录长度
  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 = 0;                                //记录主串S当前位置
 22     int j = 0;                                //记录子串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 + 1;                    //主串S的当前位置i回溯到j==0时i位置的下一位置
 37             j = 0;                            //子串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 -1;                            //若不是,说明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 = 0;                                //T的后缀位置
 53     int j = -1;                                //T的前缀位置
 54     next[0] = -1;                            //next数组的首位赋值为-1
 55     while(i < Tlength)                        //确保后缀位置小于串长
 56     {
 57         if(j == -1 || 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 = 0;                                //记录S的当前位置
 73     int j = 0;                                //记录T的当前位置
 74     int next[255];                                //next数组
 75     Get_Next(T, next);                        //调用Get_Next函数,为next赋值
 76     int count = 0;
 77 //    printf("KMP算法中j回溯的值为:");
 78     while(i < Slength && j < Tlength)
 79     {
 80 //        printf("%d ", j);
 81 //        count++;
 82         if(j == -1 || 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;                            //若不是,返回-1
 97 }
 98
 99 /*KMP改进版算法*/
100 void Get_Next_Val(char *T, int nextVal[])
101 {
102     int Tlength = StringLength(T);            //获得子串T的长度
103     int i = 0;                                //记录后缀位置
104     int j = -1;                                //记录前缀位置
105     nextVal[0] = -1;                        //next数组第一位置赋值为-1
106     while(i < Tlength)
107     {
108         if(j == -1 || 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 = 0;                                //记录S的当前位置
127     int j = 0;                                //记录T的当前位置
128     int next[255];                                //next数组
129     Get_Next_Val(T, next);                        //调用Get_Next函数,为next赋值
130     int count = 0;
131     printf("KMP_Val算法中j回溯的值为:");
132     while(i < Slength && j < Tlength)
133     {
134         printf("%d ", j);
135         count++;
136         if(j == -1 || 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;                            //若不是,返回-1
151 }
152
153
154
155 void main()
156 {
157     char *S = "aaaaaaaaaaaaaaaaaaaaabcde";
158     char *T = "aaaaaaaaaaaaaaaaaaaaaaaax";
159     int pos;
160     pos = Index(S, T);
161     if(pos != -1)
162         printf("朴素匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos);
163     else
164         printf("朴素匹配算法:子串T不存在与主串S中\n");
165     printf("---------------------------------------------------------------------\n");
166     int pos_KMP;
167     pos_KMP = Index_KMP(S, T);
168     if(pos_KMP != -1)
169         printf("KMP匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos_KMP);
170     else
171         printf("KMP匹配算法:子串T不存在与主串S中\n");
172     printf("---------------------------------------------------------------------\n");
173     int pos_KMP_val;
174     pos_KMP_val = Index_KMP_Val(S, T);
175     if(pos_KMP_val != -1)
176         printf("KMP_Val匹配算法:子串T在主串S的下标为%d的位置上开始出现\n", pos_KMP_val);
177     else
178         printf("KMP_Val匹配算法:子串T不存在与主串S中\n");
179 }

原文地址:https://www.cnblogs.com/yurui/p/10357741.html

时间: 2024-10-06 16:34:35

串的匹配算法--C语言实现的相关文章

数据结构-串的匹配算法拓展

字符串匹配算法及另外的操作 字符串匹配+统计比较次数 /***字符串匹配算法***/ #include<cstring> #include<iostream> using namespace std; #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; #define MAXSTRLEN 255 //用户可在255以内定义最长串长 typedef struct { //0号单元存放串的长度 cha

串的匹配算法之朴素算法

朴素算法,即不对子串进行预处理. 利用朴素算法我们可以在主串中寻找子串出现的次数. 代码一: 1 #include <stdio.h> 2 #include <string.h> 3 4 int Count(char *p, char *q) 5 { 6 int i, k, num = 0; 7 unsigned int j; 8 for (i = 0; p[i] != '\0'; i++) 9 { 10 for (k = i, j = 0; p[k] == q[j] &&

括号匹配算法 C语言实现

#include <stdio.h> #include <malloc.h> //malloc,realloc #include <math.h> //含有overflow #include <process.h> //exit() #define S_SIZE 100 //栈的空间大小 #define STACKINCREAMENT 10//增加空间 struct SqStack{ int *base; //栈底 int *top; //栈顶 int st

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

课本源码部分 第4章  串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceString.c        相关测试数据下载

串的模式匹配算法

今天复习数据结构,发现自己之前忽视了很久的一个算法,关于求串的匹配算法.这里有两种解决办法. 其一是常规解决思路对串进行挨个匹配,若以i指向主串,j指向匹配串,则在匹配过程中需要不停的回溯i指针,假设T={ababcabababab} S={ababa} 我们可以发现该算法在匹配时,一旦遇见不匹配的情况指针i就会回溯,同时产生了大量不需要的匹配过程.尤其是当遇见如T={AAAAAAAAAAAAAAAAAAAAAAB} S={AAAB}这类情况时时间复杂度为O(n*m) 代码实现 方法二KMP 这

4.2 串的模式匹配算法

<?php header("content-type:text/html;charset=utf-8"); class Linear_string{ /** * 串模式匹配算法 * *包括 * 1.串的初始化 __contruct() * 2.朴素的模式匹配算法 index() * 3.KMP模式匹配算法 * 4.改进的KMP模式匹配算法 */ private $string; private $length; //构造函数 public function __construct

java实现串的匹配和替换

/** *测试类,测试两个功能类,MatchBrote_force类和subString_act类的功能实现*创建的类为TestMatchBrote_force *@author LZ *@vesion 6.2 */ //import com.edu.software.LZ.*; public class TestMatchBrote_force { public static void main(String[] args){ /** *新建对象调用MatchBrote_force类*得到字串

自动机理论、语言和计算导论 by John E. Hopcroft

计算理论是计算机应用的基础,理论和应用缺一而不可. ---- 目录 ---- C01 自动机 C02 有穷自动机 C03 正则表达式与正则语言 C04 正则语言的性质 C05 上下文无关文法及上下文无关语言 C06 下推自动机 C07 上下文无关语言的性质 C08 图灵机 C09 不可判定性 C10 难解问题 C11 其他问题类 ---- C01 自动机 ---- 有穷自动机(FA)的两个重要因素是状态和跳转,状态是数据/环境,跳转是函数/响应. 自动机的结构表示法有两种,一种是正则表达式,正则

【语言对比】JSON的编解码

JAVA.Python和C++对于json的处理,都可以通过第三方库来完成,语言本身都不支持.下面以常用的场景对比这三中语言在处理json上的优缺点.下面以java的jackson库.python的simplejson库以及c++的jsoncpp库作为各自语言的代表 1.把对象转换为json串 s1为各自语言定义好的类实例 JAVA: ObjectMapper objMapper = new ObjectMapper(); objMapper.writeValueAsString(s1) Pyt