字符串一个字不对就匹配不上一直困扰着我们,

使用递归方法实现字符串模糊顺序匹配。

例如:

字符串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端口)】";

无法匹配优化后可以匹配。

 优化后代码