数据结构_串_串的模式匹配_KMP/BF
2017-01-01 20:24
281 查看
串是由零个或者多个字符组成的有序序列,又名叫字符串。在串中涉及到一下几个概念:串的长度、空串、子串、以及串的比较和串的模式匹配。
串的比较:
计算机中使用的是标准的ASCII编码,是由7位二进制数表示一个字符,总共可表示2^7=128个字符,后来由于特殊符号的出现,扩展成8位二进制数表示一个字符,共表示2^8=256个字符。再后来由于世界上的语种非常的多,就产生了Unicode编码,用16位二进制数表示一个字符,总共可表示2^16=6.5万多个字符。当然,Unicode编码的前256个字符和ASCII码完全相同。而字符串的比较则是逐位按照ASCII码的大小进行比较,那么软件中查取相应单词的过程就是这样产生的。
串的模式匹配:
普通的模式匹配算法:
KMP算法模式匹配: 对于普通的模式匹配算法而言,当des = "abcdefgoogle"和src = "google"的时候,时间复杂度
为O(n+m);而当des = "000000000000000001"和src = "00001"的时候,时间复杂度则变成了O((n-
m+1)*m),时间复杂度很高。而这其中产生时间消耗的主要是重复的比较造成的。我们假设i为des
的下标,j为src的下标,KMP算法的核心就是i不回溯(不回退),而j根据子串中是否有重复的问题
进行选择性回退,j的回退与主串无任何关系。那么j到底回退到什么位置合适,则由next数组和
nextval数组确定。
【next数组】
next数组的计算相当的简单,不同的教材上方法可能有些许差异,即:next[0] = 0 或者 next[0] = -1;
例:char arr[] = "a b a b a a a b a";
int next[] = {0, 1, 1, 2, 3, 4, 2, 2, 3};
【nextval数组】
nextval数组是next数组的一个改进版本。需要注意的是当next[0] = 0时,next数组的值是表示的第几个元素,当
next[0] = -1的时候,表示的是当前下标为next数组值得元素。
例: char arr[] = "a b a b a a a b a";
int nextval[] = {0, 1, 0, 1, 0, 4, 2, 1, 0};
KMP算法next版本实现:
KMP算法nextval版本实现:
串的比较:
计算机中使用的是标准的ASCII编码,是由7位二进制数表示一个字符,总共可表示2^7=128个字符,后来由于特殊符号的出现,扩展成8位二进制数表示一个字符,共表示2^8=256个字符。再后来由于世界上的语种非常的多,就产生了Unicode编码,用16位二进制数表示一个字符,总共可表示2^16=6.5万多个字符。当然,Unicode编码的前256个字符和ASCII码完全相同。而字符串的比较则是逐位按照ASCII码的大小进行比较,那么软件中查取相应单词的过程就是这样产生的。
串的模式匹配:
普通的模式匹配算法:
#include #include #include using namespace std; int BF(const char *des, const char *src, int pos)//返回下标 { if (des == nullptr || src == nullptr) { return -1; } int lend = strlen(des); int lens = strlen(src); if (pos < 0 || p >= lend) { return -1; } //while循环进行查找 int i = pos; int j = 0; while (i < lend && j < lens) { if (des[i] == src[j]) { ++i; ++j; } else { i = i-j+1; j = 0; } } if (j >= lens) { return i-j; } return -1; } int main() { return 0; }
KMP算法模式匹配: 对于普通的模式匹配算法而言,当des = "abcdefgoogle"和src = "google"的时候,时间复杂度
为O(n+m);而当des = "000000000000000001"和src = "00001"的时候,时间复杂度则变成了O((n-
m+1)*m),时间复杂度很高。而这其中产生时间消耗的主要是重复的比较造成的。我们假设i为des
的下标,j为src的下标,KMP算法的核心就是i不回溯(不回退),而j根据子串中是否有重复的问题
进行选择性回退,j的回退与主串无任何关系。那么j到底回退到什么位置合适,则由next数组和
nextval数组确定。
【next数组】
next数组的计算相当的简单,不同的教材上方法可能有些许差异,即:next[0] = 0 或者 next[0] = -1;
例:char arr[] = "a b a b a a a b a";
int next[] = {0, 1, 1, 2, 3, 4, 2, 2, 3};
【nextval数组】
nextval数组是next数组的一个改进版本。需要注意的是当next[0] = 0时,next数组的值是表示的第几个元素,当
next[0] = -1的时候,表示的是当前下标为next数组值得元素。
例: char arr[] = "a b a b a a a b a";
int nextval[] = {0, 1, 0, 1, 0, 4, 2, 1, 0};
KMP算法next版本实现:
#include #include #include #include #include using namespace std; void findNext(const char *src, int *next) { //入口检查 if (src == nullptr || next == nullptr) { return ; } int i = 1;//表示当前要求next数组元素的下标 int j = 0;//表示next的数组元素 next[0] = -1; next[1] = 0; int lens = strlen(src); while (i < lens) { //此处的j == 0保证不会出现 j==-1的情况 if (j==0 || src[i] == src[j]) { ++i; ++j; next[i] = j; } else { j = next[j]; } } } int KMP(const char *des, const char *src, int pos) { if (des == nullptr || src == nullptr) { return -1; } int lend = strlen(des); int lens = strlen(src); int i = pos; int j = 0; //动态创建next数组 int *next = new int[100]; findNext(src, next); while (i < lend && j < lens) { if (j==-1 || des[i] == src[j]) { ++i; ++j; } else { j = next[j]; } } delete []next; if (j > lens) { return i-lens; } else { return -1; } } int main() { char *des = "abcdefgoogle"; //char *src = "ef"; //char *src = "le"; //char *src = ""; //char *src = nullptr; char *src = " "; int pos = KMP(des, src, 2); cout<
KMP算法nextval版本实现:
#include #include #include #include void findNextVal(const char *src, int *nextval) { if (src == nullptr || nextval == nullptr) { return ; } int lens = strlen(src); if (lens == 0) { return ; } nextval[0] = -1; nextval[1] = 0; int i = 1; int j = 0; while (i < lens) { if (j == 0 || src[i] == src[j]) { ++i; ++j; if (src[i] != src[j]) { nextval[i] = j; } else { nextval[i] = nextval[j]; } } else { j = nextval[j]; } } } int KMP(const char *des, const char *src, int pos) { if (des == nullptr || src == nullptr) { return -1; } int lend = strlen(des); int lens = strlen(src); if (pos < 0 || pos >= lend) { return -1; } int i = pos; int j = 0; int nextval[100]; findNextVal(src, nextval); while (i < lend && j < lens) { if (j == 0 || des[i] == src[j]) { ++i; ++j; } else { j = nextval[j]; } } if (j >= lens) { return i-j; } else { return -1; } } int main() { char *des = "abcdefgoogle"; //char *src = "ef"; //char *src = "le"; //char *src = ""; //char *src = nullptr; char *src = " "; int pos = KMP(des, src, 2); cout<
相关文章推荐
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)