本文章是对于多关键词匹配的两种个人解决方案的介绍,只是想记录一下自己的想法而已,不喜勿喷! ^_^
   最简单也是对于我们来说最方便的解决多关键词匹配的方法就是:从数据库中把关键词列表取出,然后对待检索文章进行扫描,这势必会导致多次扫描同一篇文章,假如关键词列表数据量过大的话,势必会导致会扫描这篇文章非常多次,这就导致了非常大的性能浪费。那么下面的两种方案就是为了让扫描文章的次数尽量向1次靠近,也就是说只扫描1次,就可以匹配出多个关键词,但这显然是比较困难的,所以是尽量向1次靠近。
   一、采用反向思维检索数据库
普通的方法中,我们是先提取出所有的关键词列表,然后去扫描文章,与关键词相对比,这样的方法就忽略了数据库的高效检索能力,而把所有的检索工作带到服务器上完成;那么我们可以利用反向思维去改进这个方法,那就是我们不利用关键词列表去跟文章相对比,而是通过分割文章,让文章的每个分割单元作为过滤条件去发出SQL检索,那么就会利用到数据库的高效检索能力,并且会把客户服务器中检索算法的时间复杂度降低到一个可以接受的程度,具体如下:
    1.分割文章:假设文章的长度为m,关键词的最大长度为k,那么通过简单的数学运算可以得知:文章分割单元的总数为k×[(-1/2)×k+m+1/2],因此单考虑服务器中的分割算法的时间复杂度的话,该时间复杂度只与文章长度m和关键词长度k有关,与关键词数量无关。
    -示例:假设文章长度30,关键词最大长度为10,则:
        -当分割单元长度为1时,有30个分割单元
        -当分割单元长度为2时,有29个分割单元
        -当分割单元长度为3时,有28个分割单元
        -当分割单元长度为4时,有27个分割单元
        -..........................................................................
        -当分割单元长度为10时,有21个分割单元
        -所以分割单元总和为一个等差数列的和,化简后即为:10×[(-1/2)×10+30+1/2]=255(个)-分析:若单考虑客户服务器的性能问题的话,这种思路的算法时间复杂度与关键词的数量无关,对服务器性能有很好的提高。
    2.发起数据库检索(sql检索):接着以上话题,在每次分割到一个数据单元后就要发起一次数据库检索,也就是说算法的时间复杂度还要乘上发起一次数据库检索所需要的时间(因为该操作不是简单操作)。
    -示例:沿用第一点的示例,共有255个分割单元,则每一次的检索时间跟很多因素有关
        -关键词数量,若关键词数量较大,则检索时间也会增加。
        -数据库服务器当时的负载大小,负载大的话,检索时间会相应的增加。
        -数据库服务器是否为本地服务器,若要通过网路传输,则每次检索所需时间将会大大增加。
    -分析:所以若考虑数据库服务器的话,有很多不稳定的因素会影响到每次检索所需的时间,而且关键词数量也会影响到检索所需时间。所以这种做法只是把客户服务器中的一部分工作给数据库服务器做,减轻了客户服务器的工作,但是检索时间也受到了服务器之间交互所需时间的影响。最后我认为该方案比传统的方案有很大的进步,但是任需要继续改进。
   二、 构造关键词线索树
    这个方案就是为了解决第一个方案中存在的检索时间过长的而设计的。本方案采用的是在客户服务器采用线索树构造一个关键词缓存,这样的话每次检索的时候都是通过客户服务器的缓存进行检索,省去了不必要的服务器间交互所需时间,另外采用线索数也是为了尽量减少每次检索所需的时间,具体如下:
    1.构造关键词线索树:每次服务器启动的时候,都要从数据库中把所有的关键词取出,然后构造成如下线索树:
    -假设有ABC,ABDE,ABFG,AH,IB,JK,IBL,M,NO,NBL,NBLP 等关键词。
    -分析:在构造线索树时,假设关键词数量为n,最大关键词长度为k,则每构造一个关键词最差的情况下需要检索k个节点,那么最差的情况下总共需要检索k×n个节点,即算法的时间复杂度为O(n),因此在服务器初次构造线索树的时候,需要耗费的时间是与关键词数量n成正比的,因此当n比较大的时候,耗时是比较大的;为了减少下次(除初次以外)构造线索树的耗时,可以使用xml文档,记录下树的结构,然后先根据xml文档还原以往的树结构,再去更新数据库中新更新的关键词。这样就可以大大减少创建线索树的耗时。具体代码看文末(没有写构造xml的码)!
    2. 检索关键词:当需要检索关键词时,就将文章切割成char数组,一个一个字符的比较,并且每个可以作为关键词最后一个字符的节点,会记录以这个字符结尾的关键词的长度len(若不能作为关键词最后一个字符,则为-1,根节点为-2);
    -示例:假设要检测的文章为ASABDEND,里面有关键词ABDE。
        1--检索第1个字符A: 在根的子节点中的A节点中,A中的len为-1。标记第1个字符A为开始符,进入到以 A为根的树中,检索文章的下一个字符。
        2--检索第2个字符S:不在A的子节点中,且该字符不是文章的最后一个字符,回到以根为根节点的树中,继续检索开始符A的下一字符。
        3--检索第2个字符S:不在根的子节点中,则标记第2个字符S为开始符,继续检索开始符S的下一字符。
        4--检索第3个字符A:在根的子节点中的A节点中,A中的len为-1。标记第3个字符A为开始符,进入到以A为根的树中,检索文章的下一字符。
        5--检索第4个字符B:在A的子节点中的B节点中,B的len为-1。进入以B为根的树中,检索文章下一字符。
        6--检索第5个字符D:在B的子节点中的D节点中,D的len为-1。进入以D为根的树中,检索文章下一字符。
        7--检索第6个字符E:在D的子节点中的E节点中,E的len为4>0,找到一个匹配的关键词。回到以根为节点的树种,检索文章下一字符。
 8--检索第7个字符N:在根的子节点中的N节点中,N的len为-1。进入以N为根的树种,检索文章下一字符。
        9--检索第8个字符D:不在N的子节点中,并且该字符为文章的最后一个字符,检索完毕。
    -分析:第1步进入了和关键词比对的环节,到第2步后就发现以A开头的关键词没有第2个字符为S的关键词,就退出和关键词比对的环节,回到文章的下一字符串,看是否能够进入和关键词比对的环节,直到找到一个len为正数的节点就为匹配了一个关键词,就可以在关键词的下一字符重复以上操作,直到最后文章最后一个字符检索完毕。
    假设与关键词比对的环节每次都是最糟糕的情况,即每次都比较到最大长度的关键词,则此环节要检索关键词最大程度k次,另外对于文章的每一个字符都要发起对关键词的比较,要发起文章长度m次,因此该算法的最差的时间复杂度为O(km)。则此算法与关键词的数量没有关系,只与文章长度和最大关键词长度有关,然而最大关键词长度一般不会很大,所以次算法主要取决于文章的长度,因此就很接近于扫描1次文章就完成关键词匹配的目标了。
    总而言之,这种方案在检索关键词时耗时相当少,并且也没有多余的服务器之间交互所浪费的时间,只是在服务器第一次创建线索树时需要耗费比较多的时间,也就是在服务器启动的时候。而我觉得在服务器启动时耗时来换取检索关键字时的时间是非常有价值的,我个人比较偏向于这种方案。
public class MatchKeyword02 {public static Node root = new Node();public void add(String str){//添加关键词int strLen = str.length();if (strLen <= 0){//添加的关键词为空,则不做任何操作return;}char[] charArray = str.toCharArray();Node newNode = root;Node addNode;for (int i=0; i<strLen; i++){if (newNode.nextNodes == null){//若该节点下无任何节点,则实例化一个hashMapnewNode.nextNodes = new HashMap<Character, Node>();}addNode = newNode.nextNodes.get(new Character(charArray[i]));//获取该节点下的key为关键词第i个字符的节点if (addNode == null){//若该节点下不存在关键词的第i个字符对应的节点,就添加这个字符对应的节点if (i == strLen-1){//若时关键词的最后一个字符,则在添加该节点时要设置这个关键词的长度addNode = new Node(charArray[i],strLen);}else{addNode = new Node(charArray[i]);}newNode.nextNodes.put(new Character(charArray[i]), addNode);}newNode = addNode;//进入以关键词第i个字符对应节点为根的树}}public boolean check(String srcStr){//检查是否存在关键词int strLen = srcStr.length();if (strLen <= 0){//若文章长度为0,则肯定不存在关键词return false;}char[] charArray = srcStr.toCharArray();Node newNode;Node searchNode;for (int i=0; i<strLen; i++){newNode = root;for (int j=i; j<strLen; j++){//进入与关键词比对的环节searchNode = newNode.nextNodes.get(new Character(charArray[j]));//获取文章中该字符在树种对应的节点if (searchNode == null){//若没有该节点,说明没有以上前缀的关键词存在,则跳出关键词比对环节break;}else {if (searchNode.length > 0){//若有该节点,就判断该节点是否是某一关键词的最后一个字符,若是,说明匹配到了关键词return true;}else {newNode = searchNode;//若不是某关键词的最后一个字符,就进入到以该字符为根的树中}}}}return false;}public String filter(String srcStr, char replaceChar){//过滤关键词,并且把关键词替换成替换词,返回替换后的字符串int strLen = srcStr.length();if (strLen <= 0){return srcStr;}char[] charArray = srcStr.toCharArray();Node newNode;Node searchNode;for (int i=0; i<strLen; i++){newNode = root;for (int j=i; j<strLen; j++){searchNode = newNode.nextNodes.get(new Character(charArray[j]));if (searchNode == null){break;}else {if (searchNode.length > 0){for (int k=j; k>j-searchNode.length; k--){//若匹配到一个关键词,就把对应的关键词替换成替换符charArray[k] = replaceChar;}i = j;//跳到文章中该关键词下一字符开始扫描break;//跳出关键词比较环节}else {newNode = searchNode;}}}}return new String(charArray);}private static class Node{private char value;private int length = -1;//表示该节点不是根节点,并且也不是关键词的最后一个字符private HashMap<Character, Node> nextNodes;private Node(){this.length = -2;//表示该节点为根节点}private Node(char value){this.value = value;}private Node(char value, int length){this.value = value;this.length = length;}}
}

多关键词匹配个人解决方案相关推荐

  1. 二部图最大权匹配_12,百度竞价推广账户搭建,关键词匹配-网络运营文字版

    视频版在https://www.toutiao.com/c/user/5729041189/#mid=6430967986 视频里面 第二部,搭建账户 搜索推广的账户结构由账户.推广计划.推广单元和关 ...

  2. 搜索不包含关键词_sem竞价代运营丨做竞价推广,关键词匹配才是重点

    竞价推广初期,很多企业都会遇到同样的问题,那就是如何设置关键词匹配模式?各种匹配模式下关键词是如何对应的? 简单来说,在用户进行搜索时,根据搜索习惯的不同,系统会自动挑选对应关键词,将推广结果展现给用 ...

  3. 手把手教你做关键词匹配项目(搜索引擎)---- 第九天

    第九天 回顾: 8. 手把手教你做关键词匹配项目(搜索引擎)---- 第八天 7. 手把手教你做关键词匹配项目(搜索引擎)---- 第七天 6. 手把手教你做关键词匹配项目(搜索引擎)---- 第六天 ...

  4. 关键词匹配(Ac自动机模板题)

    2772: 关键词匹配 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 10  Solved: 4 [Submit][Status][Web Board ...

  5. python关键字匹配_python通过BF算法实现关键词匹配的方法

    本文实例讲述了python通过BF算法实现关键词匹配的方法.分享给大家供大家参考.具体实现方法如下: #!/usr/bin/python # -*- coding: UTF-8 # filename ...

  6. 手把手教你做关键词匹配项目(搜索引擎)---- 第二十一天

    客串:屌丝的坑人表单神器.数据库那点事儿 面向对象升华:面向对象的认识----新生的初识.面向对象的番外----思想的梦游篇(1).面向对象的认识---如何找出类 负载均衡:负载均衡----概念认识篇 ...

  7. python问题关键词匹配算法_python通过BF算法实现关键词匹配的方法

    本文实例讲述了python通过BF算法实现关键词匹配的方法.分享给大家供大家参考.具体实现方法如下: #!/usr/bin/python # -*- coding: UTF-8 # filename ...

  8. python地图匹配_python通过BF算法实现关键词匹配的方法

    本文实例讲述了python通过BF算法实现关键词匹配的方法.分享给大家供大家参考.具体实现方法如下: #!/usr/bin/python # -*- coding: UTF-8 # filename ...

  9. 1秒50万字!js实现关键词匹配

    在论坛和聊天室这样的场景里,为了保证用户体验,我们经常需要屏蔽很多不良词语.对于单个关键词查找,自然是indexOf.正则那样的方式效率比较高.但对于关键词较多的情况下,多次重复调用indexOf.正 ...

  10. 微博快捷登录提示21322重定向地址不匹配(解决方案)

    微博快捷登录提示21322重定向地址不匹配(解决方案) 微博快捷登录提示21322重定向地址不匹配(解决方案) 微博快捷登录提示21322重定向地址不匹配(解决方案) 1.微博网页应用授权报错,代码: ...

最新文章

  1. Samba服务器的安装与配置
  2. android 的unregisterReceiver报错处理
  3. php实现tcp连接esp8266,ESP8266之TCP透传
  4. Excel+DDT数据驱动实例
  5. discuz 二次开发
  6. Huffman(哈夫曼)编码--又称最佳编码(最有效的二进制编码)
  7. LeetCode 336. 回文对(哈希map/Trie树)
  8. 小米9稳定版系统更新:加入水滴屏形状切换开关
  9. mysql多实例和主从区别_mysql多实例的安装以及主从复制配置
  10. 【IntelliJ IDEA】不同于ecplise的一些快捷键
  11. 让ListView中的控件失去焦点:android:descendantFocusability=blocksDescendants
  12. Android URL Scheme
  13. 科学计算机DEG进入,科学计算器的使用方法(5页)-原创力文档
  14. Intellj Idea关闭自动更新
  15. Google TPU的发展历程与思考(一)
  16. c语言程序填空题库,c语言填空题题库
  17. 三菱FX系列PLC教学课程---一个从基础讲起的电梯控制实例
  18. PHP实现货币换算的方法
  19. 拓嘉启远:拼多多购物运输中的商品能拒收吗
  20. UI设计转行交互怎么样?【萧蕊冰】

热门文章

  1. 从深圳地铁看-------以损害乘客利益为目标的营运方式
  2. VUE游戏设计:实现外星人的攻击冲击波
  3. 电脑局域网所有IP及对应MAC地址查询
  4. STM32 Roadshow 更新 | 生态伙伴演讲定档
  5. 060 steam挂卡
  6. 使用java生成mapbox-gl可读的vector tile
  7. Apache-Ant下载以及安装步骤
  8. 中国科学院大学计算机复试,被中国科学院北京计算所录取了...(复试经验)
  9. gateway笔记TODO
  10. 关于windows密码加密算法的说明