• 一种字符串搜索方法


            在阅读开源代码过程中发现一种字符串搜索方法,仔细分析之后终于搞懂其原理了。虽然不知道这种搜索方法学术上叫什么名字,但是对其构造跳转表,跳跃搜索的方式很感兴趣,所以记录下来分享一下。

    先看大致的代码:

    #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’字符)字符匹配上了也没意义,这样就直接跳过中间四个无意义的匹配过程。这就是为什么说跳转表指明了每个字符"合适"的跳转位置。



  • 相关阅读:
    pycharm的各种设置,配置
    python中文件路径的问题
    Pycharm使用的一些问题!!!
    networkx如何将图写到邻接矩阵里?
    networkX如何读取存储图的二进制.dat文件
    再次理解线性回归与梯度下降
    Python DataFrame 如何删除原来的索引,重新建立索引
    NetworkX初相识
    haproxy + keepalived + mycat 高可用与负载均衡集群配置 centos7
    otter+canal
  • 原文地址:https://www.cnblogs.com/Harry-Lord/p/4002851.html
Copyright © 2020-2023  润新知