参加 2019 Python开发者日,请扫码咨询 ↑↑↑

作者 | 宋广泽

责编 | 郭芮

来源 | CSDN(ID:CSDNnews)

前一段时间在Linux上用C语言做了一个信息管理系统,初始版本的搜索就是直接使用了C语言库文件<string.h>里的库函数strcmp。后来联想到微信/QQ等软件上的搜索就很方便,无需输入全部的信息就能查找到想要的结果,或者给出一堆结果让用户选择。于是我便开始了模糊搜索算法的探索。

模糊搜索Version1.0:

//只有返回1才视为匹配成功//错误样例:234 1230234int result_mohu(const char* key,char* str){ int i=0,j=0,f=0; while(1) {     //找到第一个相匹配的字符  if((f==0||f==1)&&str[i]==key[j])        {            i++;            j++;            f=1;        }        //已经有一个字符相匹配了再往后又不相匹配了        //便认为匹配失败  else if(f==1&&str[i]!=key[j])        {            i++;            f=2;        }  else        {            i++;        }        //匹配到结尾或出现了匹配失败的结果就退出循环  if(i==strlen(str)||j==strlen(key)||f==2)        {            break;        } } return f;}

该算法确实能够在一定程度上解决模糊搜索的问题,但是在判断匹配成功与否的时候,没有回退机制,只能一股脑地往前匹配,一旦出现有任何不相匹配的迹象就会跳出循环并返回匹配失败。

例如想要搜索的结果是1230234,而输入的关键字是234,从前往后遍历匹配串遍历到第一个23的时候算法机制就认为该匹配串有可能就是想要的结果,然而第一个23再往后一位是0,又与模式串中23之后是4的情况不符,则算法机制认为匹配失败。

以上算法是我自己构想的,没有查阅任何资料,直到最后我才发现,原来我最初构想的这个算法再仔细考虑一下就成为了模式匹配领域的著名算法BF算法,BF算法就是在上述算法的基础上加上了回退机制。然而因为我的一时冲动,直接重构了上述代码,于是便有了下面的模糊搜索Version2.0。

以上算法虽然有一些无法处理的样例,也是可以部署在实际应用中的,如智能停车场。拿出手机在地下停车场里扫描停车缴费的二维码,在输入框中按照系统要求从前往后填入车牌号,输入“鲁”则停车场内所有在山东挂牌的车牌号都显示出来供用户选择,一步一步缩小范围,再输入“A”则所有在济南挂牌的车牌号都显示出来供用户选择。

模糊搜索Version2.0:

int result_mohu(const char* key,char* str){    typedef struct    {        char son[11];    }Element;

    int i,j,k=0,l=0,m=0;

    //f=1为符合筛选条件    int f=0;

 //N1为str的长度 N2为str连续子串的个数 int N1=0,N2=0; N1=strlen(str); /*计算连续子串的个数*/ for(i=1;i<=N1;i++)  N2+=i;

    /*计算连续子串的个数*/    //i控制子字符串的长度    //j控制赋值    //k控制新的线性结构b的下标    //l控制子数组的首项在原数组中的位置    //m控制即将用作赋值的str的下标    Element *b=malloc(sizeof(Element)*N2);    for(i=1;i<=N1;i++)    {        l=0;        /*while循环内为给一个子字符串数组赋值*/        while(1)        {            m=l;            for(j=0;j<i;j++)            {                b[k].son[j]=str[m];                m++;            }            l++;            k++;            if(m==N1)                break;        }    }

    //挨个比对    for(i=0;i<N2;i++)        if(strcmp(key,b[i].son)==0)        {             f=1;             break;        }    free(b);    return f;}

以上算法过于暴力,思路是穷举出待匹配字符串的所有子串,然后再将模式串与待匹配字符串的所有子串一个一个匹配,如果存在一个完全一致的子串,则返回true。

那么"abcdef"这个字符串到底有多少个连续子片段呢?我们按照子片段的长度挨个找规律,按长度由大到小进行:长度为6的就只有"abcdef"这1个;长度为5的有2个:"abcde"和"bcdef";长度为4的有3个:"abcd"、"bcde"和"cdef";长度为3的有4个;长度为2的有5个;长度为1的有6个。所以一共有1+2+3+4+5+6=21个。想必看到这里大家已经找到了规律:若关键词的长度为n,则该关键词的连续子字符串的个数就为1+2+3+...+n。

以上算法虽然在理论上可行,但当真正部署在管理系统内的时候就会出现一种不稳定的bug,这个bug我至今都没有找出来,而且时间复杂度和空间复杂度都很高,是一种效率低下的算法。

直到有一天,在一本技术上,看到了BF算法。

模糊搜索Version3.0:

int result_mohu(const char* key,char* str){    int i=0,j=0,k=0;    int flag=0;    int len_key=strlen(key);    int len_str=strlen(str);    while(i<len_str&&j<len_key)    {        //遇到一个相同的字符就继续往后匹配        if(key[j]==str[i])        {            k++;            j++;            i++;            if(k==len_key)            {                flag=1;                break;            }        }        //又回退到最初的起点        else        {            j-=k;            i=i-k+1;            k=0;        }    }    return flag;}

以上算法在模糊搜索Version1.0的基础上加上了回退机制,就避免了234匹配1230234失败这种bug了。

需要注意的是,模式串和匹配串回退的格数不同,模式串是直接回退到第一个元素的位置上,而匹配串则回退到第一个相匹配的字符后一个字符的位置上,因为匹配串需要继续向后检索是否有匹配成功的片段。

查询搜索系统经过了一次一次的迭代升级,变成了最美好的模样。

本文所谈的模糊搜索仅仅是模糊搜索中的一种——模式匹配,还有其他种类的模糊搜索,例如近义词/同义词搜索等。模式匹配算法也不仅仅只有BF算法,还有KMP算法、KMPP算法等,感兴趣的可以多了解一下。

作者:宋广泽,青岛某普通一本大学计算机专业在校生,本科在读,学生开发者。喜欢用C/C++编写有意思的程序,解决实际问题。

(本文为 AI科技大本营转载文章,转载请微信联系 1092722531)

推荐阅读:

  • Google首页玩起小游戏,AI作曲让你变身巴赫

  • 特斯拉起诉小鹏汽车员工窃取商业机密,何小鹏回应

  • 提升效率,这十个Pandas技巧必不可少!

  • 超常用的Python代码片段 | 备忘单

  • 小米“祭出” AIoT 神器!| 技术头条

  • 工作量不断增加的微软Azure,正缩小与亚马逊AWS的差距

  • 硬核接亲!程序员被新娘要求现场写代码,结果万万没想到……

  • 理工男的网红生意, 6000万月活50万条日更的背后, 内容链还能这样操作?

  • 曝光!月薪 5 万的程序员面试题:73% 人都做错,你敢试吗?

❤点击“阅读原文”,查看历史精彩文章。

一文看懂模糊搜索1.0到3.0的算法迭代历程相关推荐

  1. 一文看懂循环神经网络-RNN(独特价值+优化算法+实际应用)

    https://www.toutiao.com/a6709772730272580107/ 卷积神经网络 – CNN 已经很强大的,为什么还需要RNN? 本文会用通俗易懂的方式来解释 RNN 的独特价 ...

  2. 一文看懂深度学习——人工智能系列学习笔记

    深度学习有很好的表现,引领了第三次人工智能的浪潮.目前大部分表现优异的应用都用到了深度学习,大红大紫的 AlphaGo 就使用到了深度学习. 本文将详细的给大家介绍深度学习的基本概念.优缺点和主流的几 ...

  3. 啤酒和尿布:一文看懂关联规则

    啤酒和尿布:一文看懂关联规则 一.关联规则 二.Apriori算法 2.1 相关概念 2.2 实现步骤 2.3 代码实现 谈到大数据在零售业的应用,不得不提到一个经典的营销案例–啤酒和尿布的故事,有个 ...

  4. 一文看懂深度学习(白话解释+8个优缺点+4个典型算法)

    本文首发自 easyAI - 人工智能知识库 原文地址:<一文看懂深度学习(白话解释+8个优缺点+4个典型算法)> 深度学习有很好的表现,引领了第三次人工智能的浪潮.目前大部分表现优异的应 ...

  5. 【从0成为1】 一文看懂Facebook广告投放的教程

    [从0成为1] 一文看懂Facebook广告投放的教程 现如今,因为长期疫情的原因,使得许多跨境电商受到影响.facebook推出shopify来助力跨境电商,随着Shopify大举进军中国,Shop ...

  6. 一文看懂卷积神经网络-CNN(基本原理+独特价值+实际应用)

    http://blog.itpub.net/29829936/viewspace-2648775/ 2019-06-25 21:31:18 卷积神经网络 – CNN 最擅长的就是图片的处理.它受到人类 ...

  7. 【深度学习理论】一文看懂卷积神经网络

    [深度学习理论]一文看懂卷积神经网络 https://mp.weixin.qq.com/s/wzpMtMFkVDDH6scVcAdhlA 选自Medium 作者: Pranjal Yadav 经机器之 ...

  8. python读取excelsheet-一文看懂用Python读取Excel数据

    原标题:一文看懂用Python读取Excel数据 导读:现有的Excel分为两种格式:xls(Excel 97-2003)和xlsx(Excel 2007及以上). Python处理Excel文件主要 ...

  9. angular 字符串转换成数字_一文看懂Python列表、元组和字符串操作

    好文推荐,转自CSDN,原作星辰StarDust,感觉写的比自己清晰-大江狗荐语. 序列 序列是具有索引和切片能力的集合. 列表.元组和字符串具有通过索引访问某个具体的值,或通过切片返回一段切片的能力 ...

最新文章

  1. 如何实现两个路由下的电脑互相访问
  2. c语言用数组实现栈的插入,C语言静态数组实现栈操作
  3. 九眼合同智能审核系统运用NLPIR大数据技术进行核查
  4. java库存审核表_JAVA库存案例
  5. 硅谷NewGen:AI棋至拐点,推动下一代技术变革
  6. 如何更高效地学习3D视觉?
  7. H5上传从微信保存的图片提示格式不对
  8. 0基础参加数学建模,最大程度冲击奖项
  9. 计算机组成原理笔记——DMA方式
  10. 大部分Python库
  11. 用 360 随身 WiFi 钓鱼
  12. 继美团重申严禁诱导强迫骑手注册成个体工商户后,饿了么也回应了
  13. 《智能制造时代的研发智慧:知识工程2.0》一第3章 隐性知识的显性化
  14. oracle 伪列访问序列,Oracle同义词与序列基础教程
  15. matplotlib绘制3D图像
  16. mybatis多表查询(一对多,多对一,多对多)
  17. python实现labelme样本自动标注
  18. utils.py 文件的理解:一些小脚本文件
  19. 磊科路由器dns服务器无响应,磊科MG1200AC的DNS抽风问题
  20. 云渲染答疑:动画渲染价格一般多少?

热门文章

  1. find ip from hostname or find hostname from ip
  2. C 语言 和 C++语言的对比学习   二 数据类型
  3. 小心陷阱:二维动态内存的不连续性
  4. linux 查看 文档 不显示注释 命令
  5. C技巧:结构体参数转成不定参数
  6. java加载图片到缓存_Android实现图片异步加载并缓存到本地
  7. Linux 下实现虚拟光驱功能,查看iso文件内容
  8. JS-只能输入中文和英文
  9. appium IOS真机测试
  10. 关于javascript的keycode