文章目录
5.2 串的定义
- 零个或多个字符组成的有限序列,又叫字符串。
5.3 串的比较
比较个数和 ASCII。
5.4 串的抽象数据类型
ADT
DATA
Operation
StrAssign(T,*chars);//生成字符串
StrCopy(T,S);//复制 S 到 T
ClearString(S);//清空
StringEmpty(S);//判断是否为空
StrLength(S);
StrCompare(S,T);
Concat(T,S1,S2); //合并
SubString(Sub,S,pos,len);//切割
Index(S,T,pos);
Replace(S,T,V);
StrInsert(S,pos,T);
StrDelete(S,pos,len);
5.5 串的存储结构
5.5.1 串的顺序存储结构
- C 语言堆动态分配 malloc()、free()
5.5.2 串的链式存储结构
-> ABCD->IG##^
最后一个结点没有被占满,用#或其他非串值字符补全
5.6 朴素的模式匹配算法
- 子串的定位操作通常称做串的模式匹配
//返回子串 t 在主串 s 中第 pos 个 字符之后的位置,不存在,返回 -1
public int index(String s,String t,int pos){
int i = pos; //从 pos 位置开始匹配 主串位置下标
int j = 0; //子串 子串位置下标
//如果 i 小于主串长度 并且 t 小于子串长度
while(i < s.length() && t < t.length()){
//如果字符相等移动
if(s.charAt(i) == t.charAt(j)){
i++;
j++;
} else { //不相等 进行回退操作
i = i - j + 1;
j = 0;
}
//说明已经找到
if(j == t.length()){
return i - j; /
}
return -1;
}
}
//最好时间复杂度 O(1)
//平均 O(n+m)
//最坏 O((n-m+1) * m)
5.7 KMP模式匹配算法
- 当 i 和 j 位置上的字母相同时,两个指针都指向下一个位置继续比较;
- 当 i 和 j 位置上的字母不同时,i 不变,j 则返回到 next[j] 位置重新比较。(暂时先不管next[]的求法,只要记得定义有next[0]=-1)
- 当 j 返回到下标为0时,若当 i 和 j 位置上的字母仍然不同,根据(2),有 j = next[0]=-1,这时只能令 i 和 j 都继续往后移一位进行比较 (同步骤(1))
/*
* 返回子串t在主串s中第pos个字符后的位置(包含pos位置)。若不存在返回-1
*/
public int index_KMP(String s, String t, int pos) {
int i = pos; //主串的指针
int j = 0; //子串的指针
int[] next = getNext(t); //获取子串的next数组
while (i < s.length() && j < t.length()) {
//当 j = -1 或者 字符相等移动
if (j == -1 || s.charAt(i) == t.charAt(j)) {
// j==-1说明了子串首位也不匹配,它是由上一步j=next[0]=-1得到的。
i++;
j++;
} else {
j = next[j];
}
}
if (j == t.length()){
return i - j;
}
return -1;
}
//next[j]:当下标为 j 的元素在不匹配时,j 要跳转的下一个位置下标。
/*
* 返回字符串的next数组
*/
public int[] getNext(String str) {
int length = str.length();
int[] next = new int[length];
int i = 0; //i 后缀指针
int j = -1; //j 前缀指针
next[0] = -1; // 1.next[0]=-1;
while (i < length - 1) { // 因为后面有next[i++],所以不是i<length
if (j == -1 || str.charAt(i) == str.charAt(j)) { // j == -1代表前后缀没有相等的部分,i+1位置的next值为0
//2.j==-1时,说明前缀没有与后缀相同的地方,最大长度为0,则 i+1 位置的next值只能为0,此时也可以表示为next[i+1]=j+1。当前缀中 j 位置的字符和后缀中 i 位置的字符相等时,next[i+1]=j+1
next[++i] = ++j; //等于前缀的长度
} else {
//当 j 位置的字符和 i 位置的字符不相等时,说明前缀在第 j 个位置无法与后缀匹配,令 j 跳转到下一个匹配的位置,即 j= next[j] 。
j = next[j];
}
}
return next;
}
next[j] = j 位置前面字符串的相同前后缀的最大长度。
5.7.1 KMP 模式匹配算法改进
public class KMP2 {
public int[] getNextval(String str) {
int length = str.length();
int[] nextval = new int[length];
int i = 0; //i 后缀的指针
int j = -1; //j 前缀的指针
nextval[0] = -1;
while (i < length - 1) {
if (j == -1 || str.charAt(i) == str.charAt(j)) {
i++;
j++;
if(str.charAt(i)!=str.charAt(j)) { //多了一个字符是否相等的判断
nextval[i] = j; //等于前缀的长度
}else {
nextval[i]=nextval[j];
}
} else {
j = nextval[j];
}
}
return nextval;
}
- 核心:部分匹配表(Partial Match Table)的数组。PMT中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。
如何更好的理解和掌握 KMP 算法?