• 串的匹配算法--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("
    j共变化了%d次
    ", 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("
    j共变化了%d次
    ", 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("
    j共变化了%d次
    ", 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的位置上开始出现
    ", pos);
    163     else
    164         printf("朴素匹配算法:子串T不存在与主串S中
    ");
    165     printf("---------------------------------------------------------------------
    ");
    166     int pos_KMP;
    167     pos_KMP = Index_KMP(S, T);
    168     if(pos_KMP != -1)
    169         printf("KMP匹配算法:子串T在主串S的下标为%d的位置上开始出现
    ", pos_KMP);
    170     else
    171         printf("KMP匹配算法:子串T不存在与主串S中
    ");
    172     printf("---------------------------------------------------------------------
    ");
    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的位置上开始出现
    ", pos_KMP_val);
    177     else
    178         printf("KMP_Val匹配算法:子串T不存在与主串S中
    ");
    179 }
  • 相关阅读:
    解决无法安装Microsoft .Net Framework 3.5
    day11-15,装饰器
    Xmanager Power Suit 6.0.0009 最新版注册激活
    eth
    MySql 8.0 版本使用navicat连不上解决
    day11
    Mybatis使用规则
    nginx的基本配置
    Mybatis分页插件PageHelper使用
    dubbo的使用
  • 原文地址:https://www.cnblogs.com/yurui/p/10357741.html
Copyright © 2020-2023  润新知