首页 > 其他分享 >对数据进行模糊匹配搜索(动态规划、最长公共子串、最长公共子序列)

对数据进行模糊匹配搜索(动态规划、最长公共子串、最长公共子序列)

时间:2023-06-11 14:47:36浏览次数:43  
标签:子串 arr const 公共 bStr aStr 最长

在搜索时常常在输入一半或者输入错误时,搜索引擎就给出智能提示。

搜索框

已知的搜索推荐主要包括以下几个方面:

  • 包含:“清华” 和 “清华大学”
  • 相似:“聊天软件” 和 “通讯软件”
  • 相关:“明星” 和 “刘亦菲”
  • 纠错:“好奇害死毛” 和 “好奇害死猫”

其中包含模糊匹配可以使用动态规划算法解决,其他几个则要大量数据进行机器学习才行。

倘若要在一堆数据中对一个关键词进行匹配搜索,传统做法是把数据拆分开,然后遍历他们,看看是否包含这个关键词,对于 “fin” 和 “finish” 这样存在包含关系的单词来说是没问题的,但是对于 “fish” 和 “finish” 这样并不存在包含关系的单词就失效了,这时候期望计算出两个单词的相似性,比如 “fish” 和 “finish” 都包含 “ish”,“ish” 的长度是 3,我们可以理解相似性为 3。目前主流做法是通过最长公共子串来寻找两个或多个已知字符串最长的子串。

注:深拷贝使用了依赖库,需先安装 npm install mazey --save

最长公共子串示例:

import { deepCopy } from 'mazey';

/**
 * @method calLongestCommonSubstring
 * @description 计算两个字符串的最长公共子串
 * @param {String} aStr 字符串
 * @param {String} bStr 字符串
 * @return {Number} 长度
 */
function calLongestCommonSubstring (aStr, bStr) {
    const aLen = aStr.length;
    const bLen = bStr.length;
    // 创建二维数组并且深拷贝
    const arr = deepCopy(new Array(aLen).fill(new Array(bLen).fill(0)));
    for (let i = 0; i < aLen; ++i) {
        for (let j = 0; j < bLen; ++j) {
            if (aStr[i] === bStr[j]) {
                let baseNum = 0;
                if (i > 0 && j > 0) {
                    baseNum = arr[i-1][j-1];
                }
                arr[i][j] = baseNum + 1;
            }
        }
    }
    // 二维数组转一维数组
    const arr1 = Array.prototype.concat.apply([], arr);
    // 获取最长公共子串
    const maxLong = Math.max(...arr1);
    return maxLong;
}

calLongestCommonSubstring('fish', 'finish'); // 3

“fish” 和 “finish” 除了 “ish” 之外还共同包含 “f”,所以 “ish” + “f” 更好的表达其相似性(3 + 1 = 4),于是使用最长公共子序列对最长公共子串进行升级来查找所有序列中最长子序列,版本管理中使用的 git diff 就是建立在最长公共子序列的基础上。

最长公共子序列示例:

import { deepCopy } from 'mazey';

/**
 * @method calLongestCommonSubsequence
 * @description 计算两个字符串的最长公共子序列
 * @param {String} aStr 字符串
 * @param {String} bStr 字符串
 * @return {Number} 长度
 */
function calLongestCommonSubsequence (aStr, bStr) {
  const aLen = aStr.length;
  const bLen = bStr.length;
  const arr = deepCopy(new Array(aLen).fill(new Array(bLen).fill(0)));
  for (let i = 0; i < aLen; ++i) {
    for (let j = 0; j < bLen; ++j) {
      if (aStr[i] === bStr[j]) {
        let baseNum = 0;
        if (i > 0 && j > 0) {
          baseNum = arr[i - 1][j - 1];
        }
        arr[i][j] = baseNum + 1;
      } else {
        let [leftValue, topValue] = [0, 0];
        if (j > 0) {
          leftValue = arr[i][j - 1];
        }
        if (i > 0) {
          topValue = arr[i - 1][j];
        }
        arr[i][j] = Math.max(leftValue, topValue);
      }
    }
  }
  // 二维数组转一维数组
  const arr1 = Array.prototype.concat.apply([], arr);
  // 获取最长公共子串
  const maxLong = Math.max(...arr1);
  return maxLong;
}

calLongestCommonSubsequence('fish', 'finish'); // 4

参考

  1. 1143. 最长公共子序列 - 力扣(LeetCode)
  2. 搜索引擎如何做到模糊匹配?

版权声明

本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者后除和本文原始地址:https://blog.mazey.net/1595.html

(完)

标签:子串,arr,const,公共,bStr,aStr,最长
From: https://www.cnblogs.com/mazey/p/17472924.html

相关文章

  • Python连接两个字符串并去除首尾重复子串
    代码功能:查找两个字符串的首尾重复部分最大长度,连接两个字符串,并去除两个字符串的首尾重复部分。例如,1234和2347这两个字符串,前面字符串的234子串和后面字符串的234字串重复,两个字符串连接成为12347。参考代码与运行结果:......
  • 取公共的APIURL​
    取公共的APIURL​项目新增common目录,里面有个common.js constcommon={getapiurl(){ varapiurl=uni.getStorageSync("apiurl"); if(apiurl==undefined||apiurl==''){ apiurl="http://product.niunan.net"; uni.setStorageSync......
  • vue+elementUI 搜索栏公共组件封装,封装多搜索条件通用组件,超实用
    1、新建BaseSearch.vue文件<!--*名称:弹窗的搜索条件组件*功能:methods1.点击搜索的方法:@search2.搜索条件props:formItemList--><template><divclass="dialog-search"><el-form:inline="true"ref="......
  • 给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
    privatestaticvoidstringSubLen(Stringmsg){intmax=0;intleft=0;Map<Character,Integer>map=newHashMap<>();for(inti=0;i<msg.length();i++){if(map.containsKey(msg.charAt(i))){intdiff=i......
  • 【LeetCode滑动窗口专题#2】无重复字符的最长子串
    #1传送门滑动窗口最大值长度最小的子数组无重复字符的最长子串给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。示例2:输入:s="bbbbb"输出:1解释:......
  • 【Leetcode】5-最长回文子串
    1.一般方法:暴力for循环求解,时间复杂度,空间复杂度。2.动态规划:我们发现在匹配过程中有许多重复计算的部分,我们把这些放到一个表里保存起来会减少运算,用空间换时间。时间复杂度,空间复杂度。例如“babab”字符串对应的表为:dp[i][j]为TRUE代表字符串从i到j为回文串。判断i到j是否为回文......
  • 516. 最长回文子序列
    给你一个字符串s,找出其中最长的回文子序列,并返回该序列的长度。子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。示例1:输入:s="bbbab"输出:4解释:一个可能的最长回文子序列为"bbbb"。>动态规划classSolution{public:......
  • 647. 回文子串
    给你一个字符串s,请你统计并返回这个字符串中回文子串的数目。回文字符串是正着读和倒过来读一样的字符串。子字符串是字符串中的由连续字符组成的一个序列。具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。输入:s="abc"输出:3解释:三......
  • LeetCode 388.文件的最长绝对路径
    题目链接思路针对文件路径的特征,一个文件中一定包含.分隔符,以此为依据可以判定当前字符串是否是一个文件,文件系统是一个树形结构的角度来看的话,题中给定的字符串实际上是以一个树形结构前序遍历的序列,连续的\t表示出了当前的深度,而相邻的节点之间以\n进行分割。假设当前的路径为x/......
  • 1156. 单字符重复子串的最大长度
    如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。来源:力扣(LeetCode)链接:https://leetcode.cn/problems/swap-for-longest-repeated-......