在cmets中的正确标记,你必须与Levenshtein distance比较。
您想使用相似性百分比来比较 2 个字符串,因此我们可以将此百分比作为字符串之间的关系距离与参考字符串的长度相关联。因此,如果我们要求 100% 的相似性,我们的字符串必须绝对相等,并且字符串之间的距离为 0。相反:如果我们要求 100% 的相似性,我们的字符串必须绝对不同,并且我们的距离几乎作为参考字符串的长度(或更多)。
我将相似度百分比命名为allowedDiscrepancy,因为它提供的信息更多。所以,我的代码有方法 distance 用于计算参考字符串和另一个之间的距离和 compareWithDiscrepancy 方法,以进行关联。检查一下,它可以工作。
public class StringUtils {
public static void main(String[] args) {
final String a = "Hello, how are you doing?";
final String b = "Can I as you something?";
final String c = "Hello, how are you doing? Can I ass you something?";
// allowedDiscrepancy = 1.0 (100%) - strings might be absolutely different
//So, we have 2 strings with little difference, so it must be return "true"
assertTrue(compareWithDiscrepancy(c, String.format("%s %s", a, b), 1.0));
// allowedDiscrepancy = 0.0 (0%) - strings must be absolutely equals
//So, we have 2 strings with little difference, but more than 0, so it must be return "false"
assertFalse(compareWithDiscrepancy(c, String.format("%s %s", a, b), 0.0));
final String sameA = "Hello.";
final String sameB = "How are you?";
final String sameC = String.format("%s %s", sameA, sameB);
// allowedDiscrepancy = 1.0 (100%) - strings might be absolutely different
//So, we have 2 strings absolutely equals, so it must be return "true"
assertTrue(compareWithDiscrepancy(sameA, String.format("%s %s", sameA, sameB), 1));
// allowedDiscrepancy = 0.0 (0%) - strings must be absolutely equals
//So, we have 2 strings absolutely equals, so it must be return "true" too
assertTrue(compareWithDiscrepancy(sameC, String.format("%s %s", sameA, sameB), 0));
final String differentA = "Part 1.";
final String differentB = "Part 2.";
final String differentC = "Absolutely different string";
// allowedDiscrepancy = 1.0 (100%) - strings might be absolutely different
//So, we have 2 absolutely different strings, so it must be return "true"
assertTrue(compareWithDiscrepancy(differentC, String.format("%s %s", differentA, differentB), 1));
// allowedDiscrepancy = 0.0 (0%) - strings must be absolutely equals
//So, we have 2 absolutely different strings, so it must be return "false" too
assertFalse(compareWithDiscrepancy(differentC, String.format("%s %s", differentA, differentB), 0));
System.out.println("Done!");
}
public static boolean compareWithDiscrepancy(final String referenceString, final String testedString, double allowedDiscrepancy) {
if (allowedDiscrepancy < 0) allowedDiscrepancy = 0;
if (allowedDiscrepancy > 1) allowedDiscrepancy = 1;
int distance = distance(referenceString, testedString);
double realDiscrepancy = distance * 1.0 / referenceString.length();
if (realDiscrepancy > 1) realDiscrepancy = 1;
return allowedDiscrepancy >= realDiscrepancy;
}
static int distance(String x, String y) {
int[][] dp = new int[x.length() + 1][y.length() + 1];
for (int i = 0; i <= x.length(); i++) {
for (int j = 0; j <= y.length(); j++) {
if (i == 0) {
dp[i][j] = j;
} else if (j == 0) {
dp[i][j] = i;
} else {
dp[i][j] = min(dp[i - 1][j - 1]
+ cost(x.charAt(i - 1), y.charAt(j - 1)),
dp[i - 1][j] + 1,
dp[i][j - 1] + 1);
}
}
}
return dp[x.length()][y.length()];
}
public static int cost(char a, char b) {
return a == b ? 0 : 1;
}
public static int min(int... numbers) {
return Arrays.stream(numbers)
.min().orElse(Integer.MAX_VALUE);
}
}