数据结构课程学习记录。
串(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;
}