一种字符串搜索方法
2014-06-16 17:25
246 查看
在阅读开源代码过程中发现一种字符串搜索方法,仔细分析之后终于搞懂其原理了。虽然不知道这种搜索方法学术上叫什么名字,但是对其构造跳转表,跳跃搜索的方式很感兴趣,所以记录下来分享一下。
先看大致的代码:
跳转表数组相当于字典,下标是每个ASCII码的int值,下标对应的值是此字符在关键字中到最后一个字符的距离。比如key为“Hello!”,则关键字字符对应的跳转表为
为什说是"合适"的位置呢?
比如说源字符串“SXEI0Hello!08uix”,关键字“Hello!”,先从源字符串“SXEI0H”处从后往前匹配,匹配不成功后,选择下个位置继续从后往前的匹配过程。最笨的匹配算法肯定是往后逐个增加字符重复匹配过程,但是很多是不必要的。“SXEI0H”匹配当然是不成功的,探测下个字符‘e’。'e'在关键字中也在存在,到最后一个字符距离是4,也就是说,如果此处的‘e’跟关键字中的‘e’能匹配上(包括位置),那么后面的四个字符也应该能匹配的上,那么就可以根据跳转表直接跳到‘e’后的第四个字符开始从后往前匹配。如果‘e’后第四个字符匹配不上,那么中间四个(包括‘e’字符)字符匹配上了也没意义,这样就直接跳过中间四个无意义的匹配过程。这就是为什么说跳转表指明了每个字符"合适"的跳转位置。
先看大致的代码:
#define MAXCHAR 256 /* * key: 搜索关键字 * shift_table: 跳转表数组指针 */ void ready(string key, unsigned int *shift_table){ unsigned int k_length = key.length(); int s; for(s = 0; s < MAXCHAR ; ++s){ *(shift_table + s) = k_length; } //构造跳转表 for(s = 0; s < k_length; ++s){ *(shift_table + key[s]) = k_length - 1 - s; } } /* * key: 搜索关键字 * src: 搜索的源字符串 * n: 搜索长度 * 返回值: 关键字在源字符串中的开始位置 */ int find(string key, string src, int n){ unsigned int shift_table[MAXCHAR]; ready(key, shift_table); int i,j,pos; int s = key.length() - 1; while(s < n){ j = key.length() - 1; i = s; while( j >= 0 && (src[i] == key[j])){ --j; --i; } if( j == -1){ pos = i + 1; return pos; } ++s; if (s > n){ return -1; } s += shift_table[src[s]]; } }其中最有意思的是
//构造跳转表 for(s = 0; s < k_length; ++s){ *(shift_table + key[s]) = k_length - 1 - s; }和
s += shift_table[src[s]];这两部分分别是构造跳转表,和根据跳转表跳转到查询匹配位置。
跳转表数组相当于字典,下标是每个ASCII码的int值,下标对应的值是此字符在关键字中到最后一个字符的距离。比如key为“Hello!”,则关键字字符对应的跳转表为
shift_table[72] = 5 shift_table[69] = 4 shift_table[76] = 2 //76字符是'l'。两个'l',后面的会把前面的覆盖 shift_table[79] = 1 shift_table[33] = 0在字符查找失败时,根据跳转表可以跳转到合适的位置重新查找,避免了逐个字符循环查找的过程,提高了效率。
为什说是"合适"的位置呢?
比如说源字符串“SXEI0Hello!08uix”,关键字“Hello!”,先从源字符串“SXEI0H”处从后往前匹配,匹配不成功后,选择下个位置继续从后往前的匹配过程。最笨的匹配算法肯定是往后逐个增加字符重复匹配过程,但是很多是不必要的。“SXEI0H”匹配当然是不成功的,探测下个字符‘e’。'e'在关键字中也在存在,到最后一个字符距离是4,也就是说,如果此处的‘e’跟关键字中的‘e’能匹配上(包括位置),那么后面的四个字符也应该能匹配的上,那么就可以根据跳转表直接跳到‘e’后的第四个字符开始从后往前匹配。如果‘e’后第四个字符匹配不上,那么中间四个(包括‘e’字符)字符匹配上了也没意义,这样就直接跳过中间四个无意义的匹配过程。这就是为什么说跳转表指明了每个字符"合适"的跳转位置。
相关文章推荐
- 字符串根据多个字符进行分割的一种方法(使用split而不是regex.split更不是replace)
- str=="" str.Length==0 str==String.Empty三种方法判断字符串为空,哪一种更快?
- 《人工智能——一种现代方法》(第二版)【第6章 对抗搜索】小结
- 一种高效的搜索结果多层聚类方法
- eclipse 项目中搜索资源(类方法,文件名,文件中的字符串)(图解)
- indexOf()与lastIndexOf()方法搜索字符串
- java处理字符串搜索嵌套结构的方法
- oracle split 字符串的一种方法
- [转载] 人工智能:一种现代方法——第3章 用搜索法对问题求解
- 一种字符串表达式求值的简单方法
- PHP中一种字符串的倒置方法
- C++中字符串置空的一种方法
- indexOf()与lastIndexOf()方法搜索字符串
- 将字符串按指定字符截断分组的一种方法
- VB中字符串数组快速复制的一种方法
- 介绍一种将ASCII码字符串转换为二进制字节数据的方法
- u盘挂载中文乱码一种不彻底方法,xubuntu如何搜索可能解决方法
- Java 将字符串动态生成字节码的一种方法
- 一种格式化一定长度字符串的方法
- 位序转字符串的一种高效方法