6

各位程序员好,

我想就近乎匹配的字符串寻求一些帮助。

目前,我有一个存储描述字符串的程序,用户可以通过完全或部分输入来搜索描述。

我想实现近似匹配搜索。例如,实际描述是“hello world”,但用户错误地输入了搜索“hello eorld”。程序应该能够向用户返回“hello world”。

我尝试查看模式和匹配来实现它,但它需要一个正则表达式来匹配字符串,因此我的描述没有常规模式。我也尝试过 string.contains,但它似乎也不起作用。下面是我尝试实现的部分代码。

    ArrayList <String> list = new ArrayList<String>();
    list.add("hello world");
    list.add("go jogging at london");
    list.add("go fly kite");
    Scanner scan = new Scanner(System.in);

    for(int i = 0; i < list.size(); i++){
      if(list.get(i).contains(scan.next())) {
         System.out.println(list.get(i));
      }
    }

其他程序员可以帮我解决这个问题吗?

4

3 回答 3

3

Levenshtein 距离能够限定两个字符串之间的差异

这是一个实现形式here

public class LevenshteinDistance {
   private static int minimum(int a, int b, int c) {
      return Math.min(Math.min(a, b), c);
   }

   public static int computeLevenshteinDistance(
      CharSequence str1,
      CharSequence str2 )
   {
      int[][] distance = new int[str1.length() + 1][str2.length() + 1];

      for (int i = 0; i <= str1.length(); i++)
         distance[i][0] = i;
      for (int j = 1; j <= str2.length(); j++)
         distance[0][j] = j;

      for (int i = 1; i <= str1.length(); i++)
         for (int j = 1; j <= str2.length(); j++)
            distance[i][j] =
               minimum(
                  distance[i - 1][j] + 1,
                  distance[i][j - 1] + 1,
                  distance[i - 1][j - 1] +
                     ((str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0 : 1));

      return distance[str1.length()][str2.length()];
   }
}
于 2012-11-02T14:26:16.830 回答
2

您可以使用 LCS(最长公共子序列)查看这些: http ://en.wikipedia.org/wiki/Longest_common_subsequence_problem

public class LCS {

    public static void main(String[] args) {
        String x = StdIn.readString();
        String y = StdIn.readString();
        int M = x.length();
        int N = y.length();

        // opt[i][j] = length of LCS of x[i..M] and y[j..N]
        int[][] opt = new int[M+1][N+1];

        // compute length of LCS and all subproblems via dynamic programming
        for (int i = M-1; i >= 0; i--) {
            for (int j = N-1; j >= 0; j--) {
                if (x.charAt(i) == y.charAt(j))
                    opt[i][j] = opt[i+1][j+1] + 1;
                else 
                    opt[i][j] = Math.max(opt[i+1][j], opt[i][j+1]);
            }
        }

        // recover LCS itself and print it to standard output
        int i = 0, j = 0;
        while(i < M && j < N) {
            if (x.charAt(i) == y.charAt(j)) {
                System.out.print(x.charAt(i));
                i++;
                j++;
            }
            else if (opt[i+1][j] >= opt[i][j+1]) i++;
            else                                 j++;
        }
        System.out.println();

    }

}

其他解决方案是Aho–Corasick 字符串匹配算法, 请参见: Fast algorithm for search for substrings in a string

于 2012-11-02T14:20:04.197 回答
2

列文斯坦距离可能对这个问题有用。Apache Commons Lang StringUtils有一个实现。
此外,difference如果您想了解字符串的不同之处,来自 StringUtils 的方法可能会很有趣。

于 2012-11-02T14:25:50.997 回答