如何在java中实现字符串的近似匹配?
Posted
技术标签:
【中文标题】如何在java中实现字符串的近似匹配?【英文标题】:how to implement near matches of strings in java? 【发布时间】:2012-10-23 05:08:44 【问题描述】:各位程序员们好,
我想就字符串的近似匹配寻求一些帮助。
目前,我有一个存储描述字符串的程序,用户可以通过完全或部分输入来搜索描述。
我想实现近似匹配搜索。例如,实际描述是“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));
其他程序员可以帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:Levenshtein distance 能够限定两个字符串之间的差异
这是一个实现taken form 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()];
【讨论】:
关于你的实现:我会添加一些空字符串测试。如果 str1 为空,则距离为 str2.length()(反之亦然) 要找到“相似”的字符串,这似乎是最好的解决方案。将两个字符串都设为小写通常会更好。【参考方案2】:Levenstein Distance 可能对这个问题有用。 Apache Commons Lang StringUtils 有一个实现。另外,如果您想了解字符串的不同之处,StringUtils 中的 difference
方法可能会很有趣。
【讨论】:
我刚开始输入这个:-)【参考方案3】:您可以使用 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 string matching algorithm 请参阅: Fast algorithm for searching for substrings in a string
【讨论】:
虽然我不知道这个方法是如何工作的,但我会去看看它并想出我的方法来实现它。谢谢 SjB :D以上是关于如何在java中实现字符串的近似匹配?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Laravel 中实现 GoogleOR-Tool?特别是对于“作为最小成本流算法的分配”(Java)