【问题标题】:Rating the quality of string matches评估字符串匹配的质量
【发布时间】:2010-11-05 15:08:11
【问题描述】:

将一个模式与一组字符串逐个进行比较,同时评估模式与每个字符串匹配的数量,最好的方法是什么?在我对正则表达式的有限经验中,使用正则表达式将字符串与模式匹配似乎是一个非常二元的操作......无论模式多么复杂,最终,它要么匹配要么不匹配。我正在寻找更强大的功能,而不仅仅是匹配。有没有与此相关的好的技术或算法?

这是一个例子:

假设我有一个模式foo bar,我想从以下字符串中找到最匹配它的字符串:

foo for
foo bax
foo buo
fxx bar

现在,这些实际上都没有匹配模式,但是哪个不匹配是最接近的匹配?在这种情况下,foo bax 将是最佳选择,因为它匹配 7 个字符中的 6 个。

抱歉,如果这是一个重复的问题,当我查看这个问题是否已经存在时,我真的不知道要搜索什么。

【问题讨论】:

  • 我不确定我是否理解你的问题,正如你所说的,它要么符合模式,要么不符合,你所说的数量是什么意思,比如有多少个字符匹配?
  • 好问题;我也很好奇。
  • 是的,我想我正在寻找一种与正则表达式匹配不同的技术。对造成的误解表示歉意,换个问题...
  • @W_P,你的意思是像soundex 和/或Levenshtein distance 这样的模糊字符串算法,但是你有一个模式和一个字符串,而不是两个字符串?还是我走开了? :)
  • hmmm 还在看它,但我的第一印象是 Levenshtein 距离是我正在寻找的......我已经用我正在谈论的例子编辑了这个问题。

标签: language-agnostic string-matching levenshtein-distance


【解决方案1】:

这个可行,我查看了维基百科示例distance between "kitten" and "sitting" is 3

   public class LevenshteinDistance {

    public static final String TEST_STRING = "foo bar";

    public static void main(String ...args){
        LevenshteinDistance test = new LevenshteinDistance();
        List<String> testList = new ArrayList<String>();
        testList.add("foo for");
        testList.add("foo bax");
        testList.add("foo buo");
        testList.add("fxx bar");
        for (String string : testList) {
          System.out.println("Levenshtein Distance for " + string + " is " + test.getLevenshteinDistance(TEST_STRING, string)); 
        }
    }

    public int getLevenshteinDistance (String s, String t) {
          if (s == null || t == null) {
            throw new IllegalArgumentException("Strings must not be null");
          }

          int n = s.length(); // length of s
          int m = t.length(); // length of t

          if (n == 0) {
            return m;
          } else if (m == 0) {
            return n;
          }

          int p[] = new int[n+1]; //'previous' cost array, horizontally
          int d[] = new int[n+1]; // cost array, horizontally
          int _d[]; //placeholder to assist in swapping p and d

          // indexes into strings s and t
          int i; // iterates through s
          int j; // iterates through t

          char t_j; // jth character of t

          int cost; // cost

          for (i = 0; i<=n; i++) {
             p[i] = i;
          }

          for (j = 1; j<=m; j++) {
             t_j = t.charAt(j-1);
             d[0] = j;

             for (i=1; i<=n; i++) {
                cost = s.charAt(i-1)==t_j ? 0 : 1;
                // minimum of cell to the left+1, to the top+1, diagonally left and up +cost                
                d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1),  p[i-1]+cost);  
             }

             // copy current distance counts to 'previous row' distance counts
             _d = p;
             p = d;
             d = _d;
          } 

          // our last action in the above loop was to switch d and p, so p now 
          // actually has the most recent cost counts
          return p[n];
        }

}

【讨论】:

【解决方案2】:

这是一个有趣的问题!首先想到的是,匹配正则表达式的方式是构建一个DFA。如果您可以直接访问 built for a given regex 的 DFA(或者只是自己构建它!)您可以运行输入测量从您转换到的最后一个状态到接受状态的距离,使用最短路径作为衡量如何接近它被接受了,但我不知道有任何图书馆可以让你轻松做到这一点,即使这个措施在许多情况下也可能不会完全映射到你的直觉上。

【讨论】:

    猜你喜欢
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多