大话数据结构笔记_串

串的定义:
串(string)是由零个或者多个字符组成的有限序列, 又名叫字符串。
 

串的比较:
字典序
 

串的ADT:
string 的 ADT
ADT string
Data
串中的元素仅由一个字符组成, 相邻元素具有前驱 和 后继的关系。
Operations
StrAssign(T, *chars) : 生成一个其值等于字符串常量 chars 的 string T
StrCopy(T, S) : 串S存在, 将S复制得到T
ClearString(S) : 若串存在, 将串清空
StringEmpty(S) : 若S为空返回True , 否则返回False
StrLength(S) : 返回字符串的长度
StrCompare(S, T) : 若的S>T 返回值 >0 , s==t 返回值 = 0 , S<T 返回值 <0
Concat(T, S1, S2) : 用 T 返回由 S1 和 S2 连接而成的新串
SubString(Sub, S, pos, len) : 若S存在, 且 1=<pos<=StrLength(S) , 0=< len <=
StrLength(S) - pos + 1 ; 则sub返回其从S的pos位置开始的为len长度的字符串
Index(S, T, pos) : 若S 和 T 同时存在, 且 1=<pos<=StrLength(S), 则从pos位置开始匹配T串, 返回第一次匹配成功S中的位置
Replace(S, T, V) : 串S, T, V 同时存在, T是非空串。 用V替换S中出现的与T相等的不重叠子串。
StrInsert(S, pos, T) : 串S, T 存在, 1<=pos<=StrLength(S) + 1, 在串S的第pos个字符之前插入字符串T
StrDelete(S, pos, len) : 串S存在, 1=<pos<=StrLenth(S) - len + 1。 从串S中删除第pos个字符长度起长度len的子串。
endADT
 

 
串的顺序结构:
使用的是数组的方式来存储, 但是一般都会动态的对数组的大小进行扩容。
 

串的链式存储结构:
 
一个Node存储多少长度的字符需要根据实际情况作出调整, 每个Node大小会直接影响到字符串处理的效率。
链式存储除了在连接字符串的时候更加方便以外,整体上不如顺序存储灵活, 性能也不如顺序存储结构好。
 

模式匹配算法:
BD 匹配 : 低效。
 
KMP:
不移动主串的 i , 仅仅针对失配位置,对模式串进行调整。
 
!!! 注意: 此图是本书中使用的自定的串结构, 下标从1开始的 , 下方代码是使用C风格字符串, 下标从0开始的, 因此上述next[j] 公式修改如下:
 
 
 

KMP 算法代码实现:
以普通的C风格字符串作为例子
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NDEBUG /*需要调试信息输出请注释此宏*/
/*获取next数组*/
void get_next(const char *t, int *next)
{    
    int i,j;
    i = 0;
    j = -1;         /*调整j为-1,代表主串从失配位置下一个位置 在 和模式串重头开始匹配*/
    next[0] = -1;
    int t_len = strlen(t);

    while(i < t_len)
    {    
        if(-1 == j || t[i] == t[j])  
        {
            ++i;
            ++j;
            next[i] = j;
        }else{
            j =  next[j];
        }
    }
}

/*匹配, 在main串中匹配pattern*/
int subString(const char *s, const char *t)
{
    int i = 0;   /*指向mian串字符位置的指针*/
    int j = 0;   /*指向pattern串字符位置的指针*/
    int s_len = strlen(s);
    int t_len = strlen(t);

    int * next = (int *)malloc(sizeof(int) * (t_len));
    get_next(t, next);
     
    while(i < s_len && j < t_len)
    {
        /*等于-1 说明将i+1的位置 和 模式串的0位置的字符串在进行匹配就行了*/
        if( -1 == j || s[i] == t[j])
        {
            i++;
            j++;
        }
        else /*失配调整位置*/
        {
            
            /*下方代码块儿 输出调试信息, 方便理解KMP算法 , 可以删除*/
            {
#ifndef NDEBUG
                int len  = i - j;
                int k;
                printf("-------------------lose--------------------------\n");
                printf(" i : %d -- j : %d \n", i, j);
                printf("%s\n", s);
                for(k = 0; k<i;++k)
                    printf(" ");
                printf("^\n");
                for(k = 0; k<len;++k)
                    printf(" ");
                printf("%s\n", t);
                printf("--------------------------------------------------\n");
#endif
             }
            j =  next[j]
        }
    }

    free(next);
    if(j >=  t_len)
        return     i - t_len;
    else
        return -1;
}

int main()
{
    const char *t = "abcade";
    const char *s = "abxabdabcade";
    int result = subString(s, t);
    printf("%d\n",result);
    return 0;
}
KMP

KMP优化:
例子1:
s : da a a a a a b c x a a a a a a a
t : a a a a a a a
 
next : -1 0 1 2 3 4
 
例子2:
s:aabaabaabaaxaabaabaabaab
s:aabaabaabaab
 
如上方的例子:
在 i = 5 且 j = 5 的位置发生了失配, 那么 j 会调整到 j = 4 继续 与 i = 5 匹配 又发生失配, j又
调整到 j = 3 一直调整到 j = 0 的时候-1标志才会让 i 加1, 进而完成一次 I的调整 。可见从
s[5] != t[5] 的那次失配的其, next调整到4, 3 , 2 , 1 完全是多余的, 直接调整到 0 就行啦。
 
那么求next数组的算法进行如下优化:
 1 void get_next(const char *t, int *next)
 2 {    
 3     int i,j;
 4     i = 0;
 5     j = -1;         /*调整j为-1,代表主串从失配位置下一个位置 在 和模式串重头开始匹配*/
 6     next[0] = -1;
 7     int t_len = strlen(t);
 8 
 9     while(i < t_len)
10     {    
11         if(-1 == j || t[i] == t[j])  
12         {
13             ++i;
14             ++j;
15                         /*i = 1 时候直接设置为0, 正好j的值为0*/
16             /*否则判断 next[i] 与 next[i - 1]就行了*/
17             next[i] = ((i != 1 && str[i] == str[j]) ? next[j] : j); 
18         }
19         }else{
20             j =  next[j];      /*失配, 则将 j 回溯,这么写是确保*/
21         }
22     }
23 }
getnext数组的优化
 

猜你喜欢

转载自www.cnblogs.com/Geek-Z/p/10089279.html