【问题标题】:Regexp for Word similarity "n letter difference"单词相似性“和字母差异”的正则表达式
【发布时间】:2019-02-06 12:40:15
【问题描述】:

假设我有这样的词; 合并 。我想搜索该单词的所有 1 个字母差异组合。 aert、ert、meat、mmert、merst、merts 等都适用。所以我的正则表达式就像

[a-z]{0,2}ert OR m[a-z]{0,2}rt OR me[a-z]{0,2}t OR mer[a-z]{0,2}

所以对于 n 个字母的差异,我只需将 2 替换为 n-1 并且您无法获得所有组合。

我的问题是这样的;有没有更短的方法来编写这个正则表达式?

谢谢

【问题讨论】:

  • 您的正则表达式不适用于所有大于 1 的 n 字母差异。例如,如果 n=2mierts(有 2 个插入 m[i]ert[s])与您的不匹配正则表达式。或者这是故意的,您只是在寻找 n 大小的子字符串插入,而不是 nLevenshtein distance
  • @KevinCruijssen 感谢您指出这一点。此外,levenshtein distance 看起来很有希望。在数据库函数中应用它会很困难,但这是一个好的开始。你对正则表达式有什么建议吗?
  • 我不确定正则表达式是否适合使用变量 n Levenshtein 距离。正则表达式会很大,可能需要回溯才能知道您已经为n>1 匹配的子字符串大小。由于 MariaDB 基于 MySQL iIrc,也许搜索“Levenshtein distance MySQL function”可能会有所帮助开始搜索结果?
  • 一些正则表达式库(例如TRE、PyPi正则表达式)中有模糊匹配功能,但MariaDB中使用的PCRE库没有。

标签: java sql regex mariadb


【解决方案1】:

请检查此解决方案,我已在下面测试此代码。它似乎工作。

/**
 * Then function will return list of the words matched with nth_difference
 *
 * @param pattern search pattern
 * @param data input data
 * @param nth_difference difference
 * @return
 */
static List<String> getNthDifferenceWords(String pattern, String[] data, int nth_difference) {
    Map<Character, Integer> frequencyTable = new HashMap<>();
    List<String> matchedWords = new ArrayList<>();
    //Code complexity : O(n)
    for (int i = 0; i < pattern.length(); ++i) {
        frequencyTable.put(pattern.charAt(i), 1);
    }
    //Code complexity : O(m) where m is size of entire input;
    for (String input : data) {
        int matchCounter = 0;
        for (int j=0; j<input.length(); ++j){
            if(frequencyTable.containsKey(input.charAt(j))){
                ++matchCounter;
            }
        }
        //System.out.println("matched=" + matchCounter);
        if(input.length() <= pattern.length() && (matchCounter == pattern.length() - nth_difference)){
                matchedWords.add(input);
        }
        if((input.length() - pattern.length() == 1) && (matchCounter >= input.length() - nth_difference)){
            matchedWords.add(input);
        }
   }
    return matchedWords;
}


    public static void main(String[] args) {
    int nth_difference = 1;
    String pattern = "mert";
    String[] data = new String[]{"aert", "ert", "meat", "mmert", "merst", "merts","meritos"};
    System.out.println(getNthDifferenceWords(pattern,data,nth_difference));

    nth_difference = 2;
    pattern = "merit";
    data = new String[]{"aert", "ert", "meat", "mmert", "merst", "merts","demerit","merito", "meritos"};
    System.out.println(getNthDifferenceWords(pattern,data,nth_difference));
}

【讨论】:

    【解决方案2】:

    对于 1 个字母的差异,请按以下方式预建表。构建一个 2 列词典,第二列中包含“单词”,第一列中包含以下内容:一次一个位置,从单词中删除一个字母。

    例如:“肉”是这个词;这是表中它的行:

    `col1` `col2`
    ------ ------
    meat   meat
    eat    meat
    mat    meat
    met    meat
    mea    meat
    

    对于“见面”(注意 dup 字母):

    meet   meet
    eet    meet
    met    meet  -- only needed once
    mee    meet
    

    然后以类似的方式进行测试。搜索“mert”时,请执行

    WHERE col1 IN ('mert', 'ert', 'mrt', 'met', 'ert')
    

    请注意,您将从上面的示例中同时获得“肉”和“见面”。还要注意“met”和“meets”会发生什么。

    而且,它会检查简单的换位。搜索“元”:

    WHERE col1 IN ('meta', 'eta', 'mta', 'mea', 'met')
    

    会找到“meat”、“meet”(以及其他词,例如 met、mean、...) 可以说,“meta” -> “mean” 是 2 个字母的距离,但是哦。

    检查你的测试用例——mert vs

    aert -- 通过“ert”
    ert -- 通过“ert”
    肉——通过“遇见”
    mmert -- 通过“mert”
    merst -- 通过“mert”
    merts——通过“mert”

    同时,将PRIMARY KEY(col1, col2), INDEX(col2) 放在那张桌子上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2011-10-14
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      相关资源
      最近更新 更多