补充线性表的串,
串,一般指字符串,(string),
子串:被另一个串所包含的串,
主串:与子串对应。一般说某子串的主串,
空串:"";//十分形象
空格串:“ ”或" ";
串相等:""=""或“1”=“1”或“12”=“12”;
模式匹配:对于一个子串在主串中的位置定位。
存储方式:<数组紧缩,数组非紧缩>(顺序存储结构),链表存储,指针+堆存储...
操作集:求长度GetLength,连接串CancatStr, 求子串SubStr, 比较串EqualStr, 查找子串 IndexStr,插入串InsertStr, 删除串DeleteStr...
顺序存储结构:(下面这俩都属于顺序存储结构)
数组紧缩 :一个字符贴着另外一个字符(难以定位)(c语言是这种模式)
数组非紧缩 :每个字符4个字节(浪费空间)(顺序存储结构,要求掌握)
ps:在这里可以看到,很多时候内存空间和处理时间是矛盾的,但是可以在更需要时间的时候,用空间来交换,反之亦然,很多算法都是建立在,以空间来换时间的基础之上的。
由于紧缩比较常用,也比较难,我就只实现紧缩的操作集:
#include <iostream> #include <stdio.h> using namespace std; #define MaxSize 51 struct String { int len; char* crr; int GetLength() { len = 0; for (int i = 0; i < len; i++) { if (crr[i] == ‘\0‘) break; len++; } return len; } int GetLength(char c[]) { len = 0; for (int i = 0; i < len; i++) { if (c[i] == ‘\0‘) break; len++; } return len; } void Init(char c[]) { len = 0; crr = (char*)malloc(MaxSize); for (int i = 0; i < MaxSize; i++) { if (c[i] == ‘\0‘)break; crr[i] = c[i]; len++; } } void Free() { delete(crr); } void StrCopy(String* a)//把a的值拷贝到自身 { for (int i = 0; i <a->len; i++) { crr[i] = a->crr[i]; } len = a->len; } void ConcatStr(String* a)//把目标连到后面去 { int oldlen = len; len = len + a->len; crr[len] = ‘\0‘; for (int i = 0; i < MaxSize; i++) { if (crr[oldlen+i] == ‘\0‘)break; crr[oldlen + i] = a->crr[i]; } } int KMP(String* a)//kmp就是模式匹配的一种优化性算法 { char* arr = (char*)malloc(sizeof(a->len)); for (int i = 0; i < a->len;i++) arr[i] = 0; int j = 0; for (int i = 1; i < a->len ; i++) { if (a->crr[j] == a->crr[i]) { j++; arr[i] = j; } else { j = arr[j];//arr[j]中存放的数据的意义是:从开始往后数,已经匹配的个数,所以直接还原j为该值 } } for (int i = 0; i < a->len; i++)cout << (int)arr[i] << " "; cout << endl;//输出看看 int ret = 0; j = 0; for (int i = 0; i < len; i++)//看每一个数 { if (crr[i] == a->crr[j]) { j++; if (j == a->len) { ret = i-a->len+1; break; } } else//一个都没有匹配的 { if (j != 0) { int move = (j - arr[j - 1]); j -= move; i--; cout << move << "步" << endl; } } } return ret; } void Show() { for (int i = 0; i < len; i++) cout << crr[i]; cout << endl; } }; int main() { //bbc abcdab abcdabcdabde char* a = (char*)"bbc abcdab abcdabcdabde"; String str; str.Init(a); cout << "str = "; str.Show(); cout << endl; String str2; str2.Init((char*)"abcdabd"); //str2.StrCopy(&str); cout << "str2 = "; str2.Show(); cout << endl; //str.ConcatStr(&str2); cout<<endl; cout<<"第一次出现该子串的位置在"<<str.KMP(&str2); return 0; }
有点小看KMP算法的难度,不过这也怪我通过搜索引擎搜到的资料代码太雷同了,已经是重度优化的代码,
啃起来真的很难理解,,,这里我在理解含义后,用自己的理解写了一次没有怎么优化的KMP算法。
本来还想直接忽略串这个内容的,现在啃完KMP觉得获益匪浅,还好没有跳过。
原文:https://www.cnblogs.com/coward/p/11223488.html