数据结构——串

数据结构课程学习记录。
(String)是由零个或多个字符组成的有序数列.一般记为
S = ′ a 1 , a 2 , . . . , a n ′ S='a_1,a_2,...,a_n' S=a1,a2,...,an,其中 a i a_i ai可以是字母,数字或其它字符.
子串串中任意个连续的字符组成的子序列称为该串的子串,包含子串的串为主串.

串的存储结构

1.定长顺序存储

因为是定长的,一旦串超过了数组的最大长度,将截断,超过的部分舍去。

#define MAXLEN 255
typedef struct{
        chart ch[MAXLEN];
        int length;
}SString
2.堆分配存储表示

动态的存储方式

typedef struct{
    char *ch;
    int length;
}HString;

字符串的结尾处要使用一个结束的标志’\0’

3.块链存储表示

利用链表来存放字符串,每一个节点中可以存放一个或者多个字符串.
在这里插入图片描述

串的基本操作
StrAssign(&T,chars):赋值操作.把串T赋值为chars.
StrCompare(S,T):比较操作.若S>T,则返回值>0;若S=T,则返回值=0;若S<T,返回值<0.
StrLength(S):求串长.返回串S的元素个数.
SubString(&Sub,S,pos,len):求子串.用Sub返回S的第pos个字符串起长度为len的子串.
Concat(&T,S1,S2):串联接.用T返回由S1和S2联接而成的新串.

Index(S,T,pos):定位操作.若主串S中存在于串T值相同的子串,则返回它在主串S中第pos个字符后第一次出现的位置;否则函数值为0.
StrCopy(&T,S):复制操作.由串S复制得到串T.
StrEmpty(S):判空操作.若S为空串,则返回TRUE;若反非空,返回FALSE.
Replace(&S,T,V):替换子串作.用V替换主串S中出现的所有于T相等的不重叠的子串.
StrInsert(&S,pos,T):插入操作.在串S的第pos个字符串之前插入串T.
StrDelete(&S,pos,len):删除子串.从串S中删除第pos个字符起长度为len的子串.
ClearString(&S):清空操作.将S清空为空串.
DestroyString(&S):销毁串.将串S销毁.

Index(S,T,pos):定位操作.若主串S中存在于串T值相同的子串,则返回它在主串S中第pos个字符后第一次出现的位置;否则函数值为0.

int Index(String S, String T, int pos){
    if(pos>0){
        //初始化
        int n = StrLength(S); //主串的长度
        int m = StrLength(T); //子串的长度
        int i = pos;          //字符的位置
        String sub = NULL; //辅助变量,用来求该主串中的子串
        //n-m+1:表示我们最后搜索合法的位置
        while(i <= n-m+1 ){
            SubString(sub, S, i, m);
            if(StrCompare(sub, T) != 0)
                i++;
                else
                    return i;
        } 
    }
    return 0;
}

串的模式匹配

找到在主串中与模式串相同的那个子串的位置
  -每次找到这样一个在主串中与模式串长度相同这样一个子串
  -依次比较对应的字符是否相等
  -若有一位不相等,则不进行继续比较
  -将对应在主串当中的标记下移一位

//两个定长存储结构S(主串)和T(模式串)
//初始寻找的位置pos
int Index(SString S, SString T, int pos){
    //声明主串的标记i,初始化为开始的位置pos
    //对应模式串的标记初始化为1,表示从第一个元素开始
    int i=pos, j=1;
    //循环条件
    while(i<=s.length && j<=T.length){
        //判断当前标记对应字符是否相等
        if(S.ch[i] == T.ch[j]){
            i++;
            j++;
        }
        else{
            //如果不相同,我们要将主串当中那个子串第一个标记下移一位
            //可知,i-j+1就表示当前比较的这个子串的第一个位置,+2就是下移一位
            i=i-j+2;
            j=1;
        }
        if(j>T.length)//如果j比较到了模式串的最后一个位置
            return i-T.length;//返回的是子串当中第一个字符的位置
        else
        return 0;
    }
}

在这里插入图片描述

KMP算法

改进的模式匹配算法
‘a b a b a’
前缀除最后一个字符外,字符串的所有头部子串 {a,ab,aba,abab}
后缀除第一个字符串外,字符串的所有尾部子串{a,ba,aba,baba}
部分匹配值字符串前缀和后缀最长相等前后缀的长度,'aba’的长度为3
在这里插入图片描述

子串的最长匹配值
在这里插入图片描述
在这里插入图片描述
计算机中求解next更高效的算法:
 -初始化移动标记 i=1,当前部分匹配值 j=0, next[1]=0
 -当next[j]已经求得,则next[j+1]为:
   (1) 若子串中 t j = t i t_j=t_i tj=ti, next[i+1]=j+1
   (2) 若子串中 t j ≠ t i t_j≠t_i tj=ti, j=next[j],继续进行(1)比较

void get_next(String T,int next[]){
    int i=1, j=0;
    next[1]=0;
    while(i<T.length){
        if(j==0 || T.ch[i]==T.ch[j]){
            ++i; ++j; next[i]=j;
        }else
            j=next[j];
    }
}

在这里插入图片描述
如何运用所求解到的数组来来实现对应的KMP模式匹配算法:

int Index_KMP(String S, String T, int next[], int pos){
    //传入4个值,分别是主串S, 模式串T, 对应的数组, 初始的标记pos
    int i=pos, j=1;//j是模式串的第一个字符的位置
    while(i<=S.length && j<=T.length){
        if(j==0 || S.ch[i]==T.ch[j]){
            i++;
            j++;
        }
        else
            //此时i不用进行回退
            //j回退到对应求得的数组位置处
            j=nexxt[j];
    }
    if(j>T.length)
        return i-T.length
    else
        return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值