字符串一个字不对就匹配不上一直困扰着我们,
使用递归方法实现字符串模糊顺序匹配。
例如:
字符串1:神啊,救救我吧
字符串2:神啊救救我吧
这2个字符串能匹配6个,最大字符串长度7,那么就是6/7=0.857 如果设定匹配率为75%那么这2个字符串就是匹配。
这2个字符串有一个不匹配,如果我们设定可以容忍2个字符错误,那么这2个字符串也是匹配的。
如果实现模糊匹配呢?
分析:
字符串比较2种情况,一种是匹配上,一种没匹配上。匹配上有1种处理方法。没匹配上有3种处理方法。
匹配上:字符串都下移(1相当于光标)
神啊,救救我吧
1
1
神啊救救我吧
神啊,救救我吧
1
1
神啊救救我吧
没匹配上:字符串1不变,2下移;字符串1下移,2不变;字符串1,2都下移
字符串1不变,2下移;
救救我吧
1
1
神啊救救我吧
救救我吧
1
1
神啊救救我吧
字符串1下移,2不变;
,救救我吧
1
1
救救我吧
,救救我吧
1
1
救救我吧
字符串1,2都下移;
,救救我吧
1
1
啊救救我吧
,救救我吧
1
1
啊救救我吧
计算这3种匹配的数。取出最大值。
下面实现代码:
interface MatchHander{
boolean compare(int a,int b);
}
public class Match {
/**
* 百分之多少之内匹配错误可以接受
* a与ab匹配为百分之50的错误率。
* @param percent 设置匹配百分比
* @param src 字符串1
* @param dest 字符串2
* @param hander 匹配规则
* @return
*/
public static boolean match(double percent,String src,String dest,MatchHander hander){
char[] csrc = src.toCharArray();
char[] cdest = dest.toCharArray();
double score = 0;
score = cal(csrc,0,cdest,0,hander);
int max = csrc.length>cdest.length?csrc.length:cdest.length;
System.out.println("最小匹配百分比:"+percent+",成功匹配百分比:"+score / max);
return score / max > percent;
}
/**
* 几个错误的字符可以接受
* a与ab为1个字符错误可以接受
* @param percent 设置匹配百分比
* @param src 字符串1
* @param dest 字符串2
* @param hander 匹配规则
* @return
*/
public static boolean match(int errorNum,String src,String dest,MatchHander hander){
char[] csrc = src.toCharArray();
char[] cdest = dest.toCharArray();
int score = 0;
score = cal(csrc,0,cdest,0,hander);
int max = csrc.length>cdest.length?csrc.length:cdest.length;
System.out.println("可以接受错误数:"+errorNum+",发现错误数:"+(max - score) );
return max - score <= errorNum;
}
/**
* 2个字符串75%匹配成功返回true
* @param src
* @param dest
* @return
*/
public static boolean match(double percent,String src,String dest){
return match(percent,src,dest,new MatchHander(){
@Override
public boolean compare(int a, int b) {
return a==b;
}});
}
/**
* 2个字符串错几个字符可以接受
* @param errorNum
* @param src
* @param dest
* @return
*/
public static boolean match(int errorNum,String src,String dest){
return match(errorNum,src,dest,new MatchHander(){
@Override
public boolean compare(int a, int b) {
return a==b;
}});
}
/**
* 使用递归方法匹配字符串
* @param csrc
* @param i
* @param cdest
* @param j
* @param hander
* @return
*/
private static int cal(char[] csrc, int i, char[] cdest, int j, MatchHander hander) {
int score = 0;
if(i >= csrc.length || j >= cdest.length)
return 0;
boolean ismatch = hander.compare(csrc[i], cdest[j]);
if(ismatch){
score++;
if(i+1<csrc.length && j+1<cdest.length)
score += cal(csrc, i+1, cdest, j+1, hander) ;
}else{
int temp1 = 0;
int temp2 = 0;
int temp3 = 0;
temp1 += cal(csrc, i, cdest, j+1, hander) ;
temp2 += cal(csrc, i+1, cdest, j, hander) ;
temp3 += cal(csrc, i+1, cdest, j+1, hander) ;
int temp4 = Math.max(temp1, temp2);
score += Math.max(temp3, temp4);
}
return score;
}
public static void main(String[] args) {
//三个字符错误可以接受
System.out.println(match(3,"神啊,救救我吧","神啊救救我吧"));
//75%匹配可以接受
System.out.println(match(0.75,"神啊,救救我吧","神啊救救我吧"));
}
}
当然这个效率非常慢。10个字符之内的可以考虑。
此程序字符串
String a="N55-8P-SSK9=【产品描述:附件|Nexus 5500 存储附件(8端口)】";
String b="N55-8P-SSK9=【产品描述:配件|Nexus 5500 存储配件(8端口)】";
无法匹配优化后可以匹配。
优化后代码