zoukankan      html  css  js  c++  java
  • 串->串的表示和实现

    文字描述:

    串,就是字符串的意思。在数据结构中,串的存储方式有三种:定长顺序存储表示、堆分配存储表示和块链存储表示:

    定长顺序存储表示:  以一组地址连续的存储单元存放字符序列,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。超出预定义的串值会被舍弃,成为“截断”。

    堆分配存储表示: 以一组地址连续的存储单元存放字符序列,但它们的存储空间是在执行时动态分配而得。

    块链存储表示: 和线性表的链式存储结构类似,如下图,一个是结点大小为1的链表,一个是结点大小为4的链表;在链式存储方式中,结点大小的选择很重要,太小的话,虽然运算方便但是存储占用量大;如果太大的话,会太浪费空间。另外,它除了连接字串方便外,其他也不如前面两种存储方式灵活,一般都不用。

    串的求子串的定位函数:返回子串在主串中的位置。

    方法一,通用做法,如下图主串位置在匹配过程中可能会后退

    方法二:模式匹配的一种改进算法KMP。主串匹配的下标一直前进,没有后退。关于这个算法,虽然KMP实现的代码很短,还是并不容易理解,可以参考下https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html

    方法三:优化后的KMP。按照方法二的KMP算法,在某些情况下是有缺陷的,比如主串为“aaabaaaab”, 子串为”aaaab”的时候,匹配时,当i=4、j=3时,S.ch[4] != T.ch[4],有next[j]指示还需进行i=4,j=3; i=4,j=2; i=4,j=1这3次比较。显然j=3、2、1都为’a’,和主串中i=4的比较结果都是一样的,可以将模式一气向右滑动4个字读的位置直接进行i=5、j=1的字符比较。

    算法分析:

    一般方法求子串在主串中的位置下标的时间复杂度为n*m

    而KMP算法求子串在主串中的位置下标的时间复杂度为n+m, 另外在KMP中求串的next函数值的算法的时间复杂度为m。

    代码实现:

    串的定长顺序表示

     1 //
     2 // Created by Zhenjie Yu on 2019-04-14.
     3 //
     4 
     5 #include <stdio.h>
     6 #include <stdlib.h>
     7 #include <string.h>
     8 
     9 #define DEBUG
    10 #ifdef DEBUG
    11 #include <stdarg.h>
    12 #define LOG(args...) _log_(__FILE__, __FUNCTION__, __LINE__, ##args);
    13 static void _log_(const char *file, const char *function, int line, const char * format, ...)
    14 {
    15     char buf[1024] = {0};
    16     va_list list;
    17     va_start(list, format);
    18     vsprintf(buf+strlen(buf), format, list);
    19     sprintf(buf+strlen(buf), "
    ");
    20     va_end(list);
    21     printf(buf);
    22 }
    23 #else
    24 #define LOG
    25 #endif // DEBUG
    26 
    27 #define MAX_STRING 255
    28 typedef unsigned char SString[MAX_STRING+1]; //第一位表示串长
    29 
    30 static int Concat(SString T, SString S1, SString S2){
    31     int uncut = -1;
    32     if(S1[0]+S2[0] <= MAX_STRING){
    33         snprintf(T+1, S1[0]+1, "%s", S1+1);
    34         snprintf(T+1+S1[0], S2[0]+1, "%s", S2+1);
    35         T[0] = S1[0] + S2[0];
    36         uncut = 1;
    37     }else if(S1[0] < MAX_STRING){
    38         snprintf(T+1, S1[0]+1, "%s", S1+1);
    39         snprintf(T+1+S1[0], MAX_STRING-S1[0]+1, "%s", S2+1);
    40         T[0] = MAX_STRING;
    41         uncut = 0;
    42     }else{
    43         snprintf(T+1, MAX_STRING+1, "%s", S1+1);
    44         T[0] = MAX_STRING;
    45         uncut = 0;
    46     }
    47     return uncut;
    48 }
    49 
    50 static int StrAssign(SString T, const char chars[]){
    51     memset(T, 0, MAX_STRING+1);
    52     int len = strlen(chars);
    53     if(len > MAX_STRING){
    54         return -1;
    55     }
    56     T[0] = len;
    57     snprintf(T+1, len+1, "%s", chars);
    58     return 0;
    59 }
    60 
    61 static int SubString(SString Sub, SString S, int pos, int len)
    62 {
    63     if(pos<1 || pos>S[0] || len<0 || len>(S[0]-pos+1)){
    64         return -1;
    65     }
    66     snprintf(Sub+1, len+1, S+pos);
    67     Sub[0] = len;
    68     return 0;
    69 }
    70 
    71 int main(int argc, char *arg)
    72 {
    73     SString S1, S2, T, Sub;
    74     int ret = -1;
    75 
    76     StrAssign(S1, "test123");
    77     LOG("设置串S1的值为%s, 长度为%d", S1+1, S1[0]);
    78 
    79     StrAssign(S2, "abcdef");
    80     LOG("设置串S2的值为%s, 长度为%d", S2+1, S2[0]);
    81 
    82     ret = Concat(T, S1, S2);
    83     LOG("连接串S1和S2,并保存到变量T中,连接后T为%s, T的长度为%d", T+1, T[0]);
    84 
    85     ret = SubString(Sub, T, 4, 6);
    86     LOG("求主串T中,起始地址为4,长度为6的子串,子串结果保存咋变量Sub中; Sub的值为%s,长度为%d", Sub+1, Sub[0]);
    87     return 0;
    88 }
    串的定长顺序表示
    /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
    设置串S1的值为test123, 长度为7
    设置串S2的值为abcdef, 长度为6
    连接串S1和S2,并保存到变量T中,连接后T为test123abcdef, T的长度为13
    求主串T中,起始地址为4,长度为6的子串,子串结果保存咋变量Sub中; Sub的值为t123ab,长度为6
    
    Process finished with exit code 0

    串的堆分配存储表示及其模式匹配算法

      1 //
      2 // Created by Zhenjie Yu on 2019-04-14.
      3 //
      4 
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #define DEBUG
     10 #ifdef DEBUG
     11 #include <stdarg.h>
     12 #define LOG(args...) _log_(__FILE__, __FUNCTION__, __LINE__, ##args);
     13 static void _log_(const char *file, const char *function, int line, const char * format, ...)
     14 {
     15     char buf[1024] = {0};
     16     va_list list;
     17     va_start(list, format);
     18     vsprintf(buf+strlen(buf), format, list);
     19     sprintf(buf+strlen(buf), "
    ");
     20     va_end(list);
     21     printf(buf);
     22 }
     23 #else
     24 #define LOG
     25 #endif // DEBUG
     26 
     27 
     28 typedef struct HString{
     29     char *ch;  //如果是空串,就为NULL;否则按串长分配存储区
     30     int length; //串长度
     31 }HString;
     32 
     33 //生成一个其值等于串常量chars的串T
     34 static int StrAssign(HString *T, const char *chars);
     35 //返回S的元素个数,称为串的长度
     36 static int StrLength(HString S);
     37 //如果S大于T,则返回正值; 如果S等于T,则返回0; 否则返回负值
     38 static int StrCompare(HString S, HString T);
     39 //将S清为空串
     40 static int ClearString(HString *S);
     41 //用T返回由S1和S2连接而成的新串
     42 static int Concat(HString *T, HString S1, HString S2);
     43 //用Sub返回串S的第pos个字符起长度为Len的子串
     44 static int SubString(HString *Sub, HString S, int pos, int len);
     45 
     46 //返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0;
     47 static int Index(HString S, HString T, int pos){
     48     if(pos<0 || pos>=S.length){
     49         return -1;
     50     }
     51     int i = pos, j = 0;
     52     while(i<S.length && j<T.length){
     53         LOG("普通方法: 比较S.ch[%d]=%c 和 T.ch[%d]=%c", i, S.ch[i], j, T.ch[j]);
     54         if(S.ch[i] == T.ch[j]){
     55             i += 1;
     56             j += 1;
     57         }else{
     58             i = i-j+1;
     59             j = 0;
     60             LOG("普通方法: 两者不等,需把S的下标i回退到%d, 把T的下标j回退到%d", i, j);
     61         }
     62     }
     63     if(j>=T.length){
     64         return i-T.length;
     65     }else{
     66         return 0;
     67     }
     68 }
     69 
     70 
     71 
     72 /*********************使用KMP算法求子串位置的定位函数************************/
     73 void get_next(HString T, int next[]){
     74     int i = 1;
     75     int j = 0;
     76     memset(next, 0, T.length);
     77     next[1] = 0;
     78     int count = 1;
     79     while(i<T.length){
     80         count += 1;
     81         if(j == 0 || T.ch[i-1] == T.ch[j-1]){
     82             ++i;
     83             ++j;
     84             next[i] = j;
     85         }else{
     86             j = next[j];
     87         }
     88     }
     89 
     90     for(i=1; i<=T.length; i++){
     91         if(next[i]){
     92             next[i] = next[i]-1;
     93         }
     94         next[i-1] = next[i];
     95     }
     96 
     97     for(i=0; i<T.length; i++){
     98         LOG("KMP算法中字串(%s)的next函数值: next[%d]=%d", T.ch, i, next[i]);
     99     }
    100 }
    101 //https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html
    102 static int Index_KMP(HString S, HString T, int pos){
    103     if(pos<0 || pos>=S.length){
    104         return -1;
    105     }
    106     int i = 0;
    107     int j = 0;
    108     int *next = (int*)malloc(sizeof(int)*T.length+1);
    109 
    110     get_next(T, next);
    111 
    112     i = pos;
    113     j = 0;
    114     while(i<S.length && j<T.length){
    115         LOG("用KMP方法: 比较S.ch[%d]=%c 和 T.ch[%d]=%c", i, S.ch[i], j, T.ch[j]);
    116         if(S.ch[i] == T.ch[j] || j == 0){
    117             i += 1;
    118             j += 1;
    119         }else{
    120             j = next[j];
    121             LOG("用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到%d", j);
    122         }
    123     }
    124 
    125     free(next);
    126     if(j>=T.length){
    127         //匹配成都
    128         return i-T.length;
    129     }else{
    130         return 0;
    131     }
    132 }
    133 
    134 
    135 /*********************使用优化后的KMP算法求子串位置的定位函数************************/
    136 void get_next_Val(HString T, int nextval[])
    137 {
    138     memset(nextval, 0, T.length+1);
    139     int i = 1;
    140     int j = 0;
    141     nextval[1] = 0;
    142     while (i<T.length){
    143         if(j==0 || T.ch[i-1] == T.ch[j-1]){
    144             i += 1;
    145             j += 1;
    146             if(j && (T.ch[i-1] != T.ch[j-1])){
    147                 nextval[i] = j;
    148             }else{
    149                 nextval[i] = nextval[j];
    150             }
    151         }else{
    152             j = nextval[j];
    153         }
    154     }
    155 
    156     for(i=1; i<=T.length; i++){
    157         if(nextval[i]){
    158             nextval[i] = nextval[i]-1;
    159         }
    160         nextval[i-1] = nextval[i];
    161     }
    162 
    163     for(i=0; i<T.length; i++){
    164         LOG("优化后的KMP算法中字串(%s)的nextval函数值: nextval[%d]=%d", T.ch, i, nextval[i]);
    165     }
    166     return ;
    167 }
    168 static int Index_KMP_Val(HString S, HString T, int pos)
    169 {
    170     if(pos<0 || pos>=S.length){
    171         return -1;
    172     }
    173     int i = 0;
    174     int j = 0;
    175     int *next = (int*)malloc(sizeof(int)*T.length+1);
    176 
    177     get_next_Val(T, next);
    178 
    179     i = pos;
    180     j = 0;
    181     while(i<S.length && j<T.length){
    182         LOG("用优化后的KMP方法: 比较S.ch[%d]=%c 和 T.ch[%d]=%c", i, S.ch[i], j, T.ch[j]);
    183         if(S.ch[i] == T.ch[j] || j == 0){
    184             i += 1;
    185             j += 1;
    186         }else{
    187             j = next[j];
    188             LOG("用优化后的KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到%d", j);
    189         }
    190     }
    191     free(next);
    192     if(j>=T.length){
    193         //匹配成都
    194         return i-T.length;
    195     }else{
    196         return 0;
    197     }
    198 }
    199 
    200 
    201 
    202 int main(int argc, char *argv[])
    203 {
    204     int ret = -1;
    205     int pos = 0;
    206     HString S1, S2, T, Sub, S;
    207     S1.ch = S2.ch = T.ch = Sub.ch = S.ch = NULL;
    208     S1.length = S2.length = T.length = Sub.length = 0;
    209 
    210     ret = StrAssign(&S1, "hbcde");
    211     LOG("设置变量S1为%s", S1.ch);
    212 
    213     ret = StrAssign(&S2, "ghijklm");
    214     LOG("设置变量S2为%s", S2.ch);
    215 
    216     ret = StrCompare(S1, S2);
    217     LOG("较字符串S1和S2的大小, 返回值为%d", ret);
    218 
    219     ret = Concat(&T, S1, S2);
    220     LOG("将字符串S1和S2拼接,并将值保存到T; 结果使得变量T为%s", T.ch);
    221 
    222     ret = SubString(&Sub, T, 4, 3);
    223     LOG("求字符串T中起始4开始、长度为3的子串,并将子串放到变量Sub; 结果使得变量Sub为%s, (下标从1开始)", Sub);
    224 
    225     LOG("清空S1、S2、T、Sub变量的内容");
    226     ClearString(&S1);
    227     ClearString(&S2);
    228     ClearString(&T);
    229     ClearString(&Sub);
    230 
    231     ret = StrAssign(&S, "acabaabaabcacaabc");
    232     LOG("设置变量S为%s", S.ch);
    233 
    234     ret = StrAssign(&T, "abaabc");
    235     LOG("设置变量T为%s", T.ch);
    236 
    237     LOG("求字串S中位置pos开始,是否存在子串T; 如果存在,则返回字串T在S中的位置下标");
    238     LOG("方法一:普通方法");
    239     ret = Index(S, T, pos);
    240     LOG("普通方法: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)
    ", S.ch, pos, T.ch, ret);
    241 
    242     LOG("方法二:用KMP方法,例1");
    243     ret = Index_KMP(S, T, pos);
    244     LOG("用KMP方法,例1: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)
    ", S.ch, pos, T.ch, ret);
    245 
    246     ret = StrAssign(&S, "aaabaaaab");
    247     LOG("设置变量S为%s", S.ch);
    248 
    249     ret = StrAssign(&T, "aaaab");
    250     LOG("设置变量T为%s", T.ch);
    251 
    252     LOG("方法二:用KMP方法,例2");
    253     ret = Index_KMP(S, T, pos);
    254     LOG("用KMP方法,例2: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)
    ", S.ch, pos, T.ch, ret);
    255 
    256 
    257     LOG("方法三:用改进后的KMP方法");
    258     ret = Index_KMP_Val(S, T, pos);
    259     LOG("用改进后的KMP方法: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)", S.ch, pos, T.ch, ret);
    260     return 0;
    261 }
    262 
    263 
    264 
    265 //////////////////////////////////////////////////////////////////////////
    266 static int StrAssign(HString *T, const char *chars)
    267 {
    268     if(T == NULL){
    269         return -1;
    270     }
    271     if(T->ch){
    272         free(T->ch);
    273         T->ch = NULL;
    274     }
    275     int len = strlen(chars);
    276     if((T->ch = malloc(len+1)) == NULL){
    277         return -1;
    278     }
    279     memset(T->ch, 0, len+1);
    280     T->length = len;
    281     snprintf(T->ch, len+1, "%s", chars);
    282     return 0;
    283 }
    284 
    285 static int StrLength(HString S)
    286 {
    287     return S.length;
    288 }
    289 
    290 static int StrCompare(HString S, HString T)
    291 {
    292     int i = 0;
    293     for(i=0; i<S.length && i<T.length; ++i){
    294         if(S.ch[i] != T.ch[i]){
    295             return S.ch[i] - T.ch[i];
    296         }
    297     }
    298     return S.length - T.length;
    299 }
    300 
    301 static int ClearString(HString *S)
    302 {
    303     if(S->ch){
    304         free(S->ch);
    305         S->ch = NULL;
    306     }
    307     S->length = 0;
    308     return 0;
    309 }
    310 static int Concat(HString *T, HString S1, HString S2)
    311 {
    312     if(T->ch){
    313         free(T->ch);
    314         T->ch = NULL;
    315     }
    316     if((T->ch = (char*)malloc((S1.length+S2.length)*sizeof(char))) == NULL){
    317         return -1;
    318     }
    319     strncpy(T->ch, S1.ch, S1.length);
    320     strncpy(T->ch+S1.length, S2.ch, S2.length);
    321     T->length = S1.length + S2.length;
    322     T->ch[T->length] = '';
    323     return 0;
    324 }
    325 
    326 static int  SubString(HString *Sub, HString S, int pos, int len)
    327 {
    328     if(pos<1 || pos>S.length || len<0 || len>S.length-pos+1){
    329         return -1;
    330     }
    331     if(Sub->ch){
    332         free(Sub->ch);
    333         Sub->ch = NULL;
    334     }
    335     if(!len){
    336         Sub->ch = NULL;
    337         Sub->length = 0;
    338     }else{
    339         Sub->ch = (char *)malloc(len*sizeof(char)+1);
    340         memset(Sub->ch, 0, len);
    341         strncpy(Sub->ch, S.ch+pos-1, len);
    342         Sub->length = len;
    343         Sub->ch[len] = '';
    344     }
    345     return 0;
    346 }
    串的堆分配存储表示及其模式匹配算法
    /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
    设置变量S1为hbcde
    设置变量S2为ghijklm
    较字符串S1和S2的大小, 返回值为1
    将字符串S1和S2拼接,并将值保存到T; 结果使得变量T为hbcdeghijklm
    求字符串T中起始4开始、长度为3的子串,并将子串放到变量Sub; 结果使得变量Sub为deg, (下标从1开始)
    清空S1、S2、T、Sub变量的内容
    设置变量S为acabaabaabcacaabc
    设置变量T为abaabc
    求字串S中位置pos开始,是否存在子串T; 如果存在,则返回字串T在S中的位置下标
    方法一:普通方法
    普通方法: 比较S.ch[0]=a 和 T.ch[0]=a
    普通方法: 比较S.ch[1]=c 和 T.ch[1]=b
    普通方法: 两者不等,需把S的下标i回退到1, 把T的下标j回退到0
    普通方法: 比较S.ch[1]=c 和 T.ch[0]=a
    普通方法: 两者不等,需把S的下标i回退到2, 把T的下标j回退到0
    普通方法: 比较S.ch[2]=a 和 T.ch[0]=a
    普通方法: 比较S.ch[3]=b 和 T.ch[1]=b
    普通方法: 比较S.ch[4]=a 和 T.ch[2]=a
    普通方法: 比较S.ch[5]=a 和 T.ch[3]=a
    普通方法: 比较S.ch[6]=b 和 T.ch[4]=b
    普通方法: 比较S.ch[7]=a 和 T.ch[5]=c
    普通方法: 两者不等,需把S的下标i回退到3, 把T的下标j回退到0
    普通方法: 比较S.ch[3]=b 和 T.ch[0]=a
    普通方法: 两者不等,需把S的下标i回退到4, 把T的下标j回退到0
    普通方法: 比较S.ch[4]=a 和 T.ch[0]=a
    普通方法: 比较S.ch[5]=a 和 T.ch[1]=b
    普通方法: 两者不等,需把S的下标i回退到5, 把T的下标j回退到0
    普通方法: 比较S.ch[5]=a 和 T.ch[0]=a
    普通方法: 比较S.ch[6]=b 和 T.ch[1]=b
    普通方法: 比较S.ch[7]=a 和 T.ch[2]=a
    普通方法: 比较S.ch[8]=a 和 T.ch[3]=a
    普通方法: 比较S.ch[9]=b 和 T.ch[4]=b
    普通方法: 比较S.ch[10]=c 和 T.ch[5]=c
    普通方法: 求字串S(acabaabaabcacaabc)中位置pos(0)开始,是否存在子串T(abaabc); 返回的下标为5 (下标从0开始)
    
    方法二:用KMP方法,例1
    KMP算法中字串(abaabc)的next函数值: next[0]=0
    KMP算法中字串(abaabc)的next函数值: next[1]=0
    KMP算法中字串(abaabc)的next函数值: next[2]=0
    KMP算法中字串(abaabc)的next函数值: next[3]=1
    KMP算法中字串(abaabc)的next函数值: next[4]=1
    KMP算法中字串(abaabc)的next函数值: next[5]=2
    用KMP方法: 比较S.ch[0]=a 和 T.ch[0]=a
    用KMP方法: 比较S.ch[1]=c 和 T.ch[1]=b
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0
    用KMP方法: 比较S.ch[1]=c 和 T.ch[0]=a
    用KMP方法: 比较S.ch[2]=a 和 T.ch[1]=b
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0
    用KMP方法: 比较S.ch[2]=a 和 T.ch[0]=a
    用KMP方法: 比较S.ch[3]=b 和 T.ch[1]=b
    用KMP方法: 比较S.ch[4]=a 和 T.ch[2]=a
    用KMP方法: 比较S.ch[5]=a 和 T.ch[3]=a
    用KMP方法: 比较S.ch[6]=b 和 T.ch[4]=b
    用KMP方法: 比较S.ch[7]=a 和 T.ch[5]=c
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到2
    用KMP方法: 比较S.ch[7]=a 和 T.ch[2]=a
    用KMP方法: 比较S.ch[8]=a 和 T.ch[3]=a
    用KMP方法: 比较S.ch[9]=b 和 T.ch[4]=b
    用KMP方法: 比较S.ch[10]=c 和 T.ch[5]=c
    用KMP方法,例1: 求字串S(acabaabaabcacaabc)中位置pos(0)开始,是否存在子串T(abaabc); 返回的下标为5 (下标从0开始)
    
    设置变量S为aaabaaaab
    设置变量T为aaaab
    方法二:用KMP方法,例2
    KMP算法中字串(aaaab)的next函数值: next[0]=0
    KMP算法中字串(aaaab)的next函数值: next[1]=0
    KMP算法中字串(aaaab)的next函数值: next[2]=1
    KMP算法中字串(aaaab)的next函数值: next[3]=2
    KMP算法中字串(aaaab)的next函数值: next[4]=3
    用KMP方法: 比较S.ch[0]=a 和 T.ch[0]=a
    用KMP方法: 比较S.ch[1]=a 和 T.ch[1]=a
    用KMP方法: 比较S.ch[2]=a 和 T.ch[2]=a
    用KMP方法: 比较S.ch[3]=b 和 T.ch[3]=a
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到2
    用KMP方法: 比较S.ch[3]=b 和 T.ch[2]=a
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到1
    用KMP方法: 比较S.ch[3]=b 和 T.ch[1]=a
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0
    用KMP方法: 比较S.ch[3]=b 和 T.ch[0]=a
    用KMP方法: 比较S.ch[4]=a 和 T.ch[1]=a
    用KMP方法: 比较S.ch[5]=a 和 T.ch[2]=a
    用KMP方法: 比较S.ch[6]=a 和 T.ch[3]=a
    用KMP方法: 比较S.ch[7]=a 和 T.ch[4]=b
    用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到3
    用KMP方法: 比较S.ch[7]=a 和 T.ch[3]=a
    用KMP方法: 比较S.ch[8]=b 和 T.ch[4]=b
    用KMP方法,例2: 求字串S(aaabaaaab)中位置pos(0)开始,是否存在子串T(aaaab); 返回的下标为4 (下标从0开始)
    
    方法三:用改进后的KMP方法
    优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[0]=0
    优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[1]=0
    优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[2]=0
    优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[3]=0
    优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[4]=3
    用优化后的KMP方法: 比较S.ch[0]=a 和 T.ch[0]=a
    用优化后的KMP方法: 比较S.ch[1]=a 和 T.ch[1]=a
    用优化后的KMP方法: 比较S.ch[2]=a 和 T.ch[2]=a
    用优化后的KMP方法: 比较S.ch[3]=b 和 T.ch[3]=a
    用优化后的KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0
    用优化后的KMP方法: 比较S.ch[3]=b 和 T.ch[0]=a
    用优化后的KMP方法: 比较S.ch[4]=a 和 T.ch[1]=a
    用优化后的KMP方法: 比较S.ch[5]=a 和 T.ch[2]=a
    用优化后的KMP方法: 比较S.ch[6]=a 和 T.ch[3]=a
    用优化后的KMP方法: 比较S.ch[7]=a 和 T.ch[4]=b
    用优化后的KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到3
    用优化后的KMP方法: 比较S.ch[7]=a 和 T.ch[3]=a
    用优化后的KMP方法: 比较S.ch[8]=b 和 T.ch[4]=b
    用改进后的KMP方法: 求字串S(aaabaaaab)中位置pos(0)开始,是否存在子串T(aaaab); 返回的下标为4 (下标从0开始)
    
    Process finished with exit code 0
  • 相关阅读:
    MySQL数据库分页
    Spring MVC
    Spring框架
    Java学习计划(转载)
    开发用户注册模块
    Ajax技术
    Jodd Email 发送邮件
    DOM技术
    MD5加密
    final关键字的使用
  • 原文地址:https://www.cnblogs.com/aimmiao/p/10800380.html
Copyright © 2011-2022 走看看