1. 程式人生 > >java實現字串匹配問題之求兩個字串的最大公共子串

java實現字串匹配問題之求兩個字串的最大公共子串

轉載請註明出處:http://blog.csdn.net/xiaojimanman/article/details/38924981

最近在專案工作中有一個關於文字對比的需求,經過這段時間的學習,總結了這篇部落格內容:求兩個字串的最大公共子串。

演算法思想:基於圖計算兩字串的公共子串。具體演算法思想參照下圖:




輸入字串S1:achmacmh    輸入字串S2:macham

1)第a步,是將字串s1,s2分別按位元組拆分,構成一個二維陣列;

2)二維陣列中的值如b所示,比如第一行第一列的值表示字串s2和s1的第一個位元組是否相等,若相等就是1,否則就是0,最終產生b所示的二維陣列;

3)分別求二維陣列中斜線上的公共因子(斜線為元素a右下角值,即a[i][j]的下一個元素是a[i+1][j+1];公共因子為1所在的位置構成的字串);

4)對所有公共因子排序,返回最大的公共因子的值。

具體的實現程式碼如下所示:

package cn.lulei.compare;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class StringCompare {
	private int a;
	private int b;
	
	public String getMaxLengthCommonString(String s1, String s2) {
		if (s1 == null || s2 == null)  {
			return null;
		}
		a = s1.length();//s1長度做行
		b = s2.length();//s2長度做列
		if(a== 0 || b == 0) {
			return "";
		}
		//設定匹配矩陣
		boolean [][] array = new boolean[a][b];
		for (int i = 0; i  < a; i++) {
			char c1 = s1.charAt(i);
			for (int j = 0; j < b; j++) {
				char c2 = s2.charAt(j);
				if (c1 == c2) {
					array[i][j] = true;
				}  else {
					array[i][j] = false;
				}
			}
		}
		//求所有公因子字串,儲存資訊為相對第二個字串的起始位置和長度
		List<ChildString> childStrings = new ArrayList<ChildString>();
		for (int i = 0; i < a; i++) {
			getMaxSort(i, 0, array, childStrings);
		}
		for (int i = 1; i < b; i++) {
			getMaxSort(0, i, array, childStrings);
		}
		//排序
		sort(childStrings);
		if (childStrings.size() < 1) {
			return "";
		}
		//返回最大公因子字串
		int max = childStrings.get(0).maxLength;
		StringBuffer sb = new StringBuffer();
		for (ChildString s: childStrings) {
			if (max != s.maxLength) {
				break;
			}
			sb.append(s2.substring(s.maxStart, s.maxStart + s.maxLength));
			sb.append("\n");
		}
		return sb.toString();
	}
	
	//排序,倒敘
	private void sort(List<ChildString> list) {
		Collections.sort(list, new Comparator<ChildString>(){
			public int compare(ChildString o1, ChildString o2) {
				return o2.maxLength - o1.maxLength;
			}
		});
	}
	
	//求一條斜線上的公因子字串
	private void getMaxSort(int i, int j, boolean [][] array, List<ChildString> sortBean) {
		int length = 0;
		int start = j;
		for (; i < a && j < b; i++,j++) {
			if (array[i][j]) {
				length++;
			} else {
				sortBean.add(new ChildString(length, start));
				length = 0;
				start = j + 1;
			}
			if (i == a-1 || j == b-1) {
				sortBean.add(new ChildString(length, start));
			}
		}
	}
	
	//公因子類
	class ChildString {
		int maxLength;
		int maxStart;
		
		ChildString(int maxLength, int maxStart){
			this.maxLength = maxLength;
			this.maxStart = maxStart;
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(new StringCompare().getMaxLengthCommonString("achmacmh", "macham"));
	}
}

程式最終執行結果是:


對於兩個檔案的比對個人認為可以參照這種演算法思想(自己現在併為實現),在日後的部落格中將會寫到。

上述實現過程中,用陣列儲存了所有的公共子串資訊,然後排序取最大的子串,這種做法如果只是求最大子串的話,演算法就不是很合理,因此做了如下修改,List只儲存當前計算中最大的子串,具體實現如下:

 /**  
 *@Description: 字串比較   
 */ 
package com.lulei.test;

import java.util.ArrayList;
import java.util.List;

public class StringCompare {
	private int a;
	private int b;
	private int maxLength = -1;
	
	public String getMaxLengthCommonString(String s1, String s2) {
		if (s1 == null || s2 == null)  {
			return null;
		}
		a = s1.length();//s1長度做行
		b = s2.length();//s2長度做列
		if(a== 0 || b == 0) {
			return "";
		}
		//設定匹配矩陣
		boolean [][] array = new boolean[a][b];
		for (int i = 0; i  < a; i++) {
			char c1 = s1.charAt(i);
			for (int j = 0; j < b; j++) {
				char c2 = s2.charAt(j);
				if (c1 == c2) {
					array[i][j] = true;
				}  else {
					array[i][j] = false;
				}
			}
		}
		//求所有公因子字串,儲存資訊為相對第二個字串的起始位置和長度
		List<ChildString> childStrings = new ArrayList<ChildString>();
		for (int i = 0; i < a; i++) {
			getMaxSort(i, 0, array, childStrings);
		}
		for (int i = 1; i < b; i++) {
			getMaxSort(0, i, array, childStrings);
		}
		StringBuffer sb = new StringBuffer();
		for (ChildString s: childStrings) {
			sb.append(s2.substring(s.maxStart, s.maxStart + s.maxLength));
			sb.append("\n");
		}
		return sb.toString();
	}
	
	//求一條斜線上的公因子字串
	private void getMaxSort(int i, int j, boolean [][] array, List<ChildString> sortBean) {
		int length = 0;
		int start = j;
		for (; i < a && j < b; i++,j++) {
			if (array[i][j]) {
				length++;
			} else {
				//直接add,儲存所有子串,下面的判斷,只儲存當前最大的子串
				//sortBean.add(new ChildString(length, start));
				if (length == maxLength) {
					sortBean.add(new ChildString(length, start));
				} else if (length > maxLength) {
					sortBean.clear();
					maxLength = length;
					sortBean.add(new ChildString(length, start));
				}
				length = 0;
				start = j + 1;
			}
			if (i == a-1 || j == b-1) {
				//直接add,儲存所有子串,下面的判斷,只儲存當前最大的子串
				//sortBean.add(new ChildString(length, start));
				if (length == maxLength) {
					sortBean.add(new ChildString(length, start));
				} else if (length > maxLength) {
					sortBean.clear();
					maxLength = length;
					sortBean.add(new ChildString(length, start));
				}
			}
		}
	}
	
	//公因子類
	class ChildString {
		int maxLength;
		int maxStart;
		
		ChildString(int maxLength, int maxStart){
			this.maxLength = maxLength;
			this.maxStart = maxStart;
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(new StringCompare().getMaxLengthCommonString("abcdef", "defabc"));
	}
}


相關推薦

java實現字串匹配問題字串公共

轉載請註明出處:http://blog.csdn.net/xiaojimanman/article/details/38924981 最近在專案工作中有一個關於文字對比的需求,經過這段時間的學習,總結了這篇部落格內容:求兩個字串的最大公共子串。 演算法思想:基於圖計算兩字串

C程式設計——程式設計實現查詢字串公共2.0

1、 題目:程式設計實現查詢兩個字串的最大公共子串 示例:“aocdfe"和"pmcdfa"最大公共子串為"cdf” 注:最大公共子串有不止一個時,只輸出第一個最大子串 利用斐波那契數列數的思想 **2、**程式 #include <stdio.h> #include &

C程式設計——程式設計實現查詢字串公共1.0

1、 題目:程式設計實現查詢兩個字串的最大公共子串 示例:“aocdfe"和"pmcdfa"最大公共子串為"cdf” 注:最大公共子串有不止一個時,只輸出第一個最大子串 **2、**程式 #include <stdio.h> #include <string.h>

程式設計實現查詢字串公共

#include <stdio.h> #include <string.h> //程式設計實現查詢兩個字串的最大公共子串 //示例:"aocdfe"和"pmcdfa"最大公共子串為"cdf" void MyPub(char *str1, char *str2) {

字串操作】 尋找字串中的 公共

*題目描述:請編寫一個函式,求2個字串的最長公共子串,n<20,字元長度不超過255.       例如有2個字串為:       Name some local bus.       local bus is high speed I/O bus close to

演算法題-字串公共

題目:給定一個query和一個text,均由小寫字母組成。要求在text中找出以同樣順序連續出現在query中最長連續字母序列的長度。例如,query為“acbac”,text為“acaccbabb”,那麼text中的“cba”為最長的連續出現在query中的字元序列,因此

C語言整數

上程式碼: #include<stdio.h> #define Max(a,b) ((a>b)?(a):(b))  //預處理實現 int max(int a,int b)   //函式實現 {return a>b?a:b; } int main()

動態規劃求解字串公共問題

最大公共子串長度問題就是:求兩個串的所有子串中能夠匹配上的最大長度是多少。比如:"abcdkkk" 和 "baabcdadabc",可以找到的最長的公共子串是"abcd",所以最大公共子串長度為4。下面的程式是採用矩陣法進行求解的,這對串的規模不大的情況還是比較有效的解法。請

公共LCS(Java實現

public class Lcs { public static String longest(String s1,String s2){ char ch1[]=s1.toCharArray(); char ch

公共

#include <stdio.h> #include <string.h> int main1() { char *str1 = "aocdfe"; char *str2 = "aadapmcdfa"; int longest = 0; // 最大長度

藍橋杯java第八屆B組:公共

最大公共子串 最大公共子串長度問題就是: 求兩個串的所有子串中能夠匹配上的最大長度是多少。 比如:"abcdkkk" 和 "baabcdadabc", 可以找到的最長的公共子串是"abcd",所以最大公共子串長度為4。 下面的程式是採用矩陣法進行求解的,這對串的規模不大的情

字符公共——Java實現

求解 ont ins oid info ++ 題意 短字符串 clas 要求:求兩個字符串的最長公共子串,如“abcdefg”和“adefgwgeweg”的最長公共子串為“defg”(子串必須是連續的) public class Main03{ // 求解兩個字符號的最

python實現:字串公共

假設s1 = 'abcdef'  ,s2 = 'mcdea',建立一個(len(s1)+1) x (len(s2)+1)的陣列,如下如所示的一個二維陣列,程式碼的操作流程是: # -*- coding

java實現字串公共字串

/** * @author weichen CHEN created on 2018/4/20 * @version 2018/4/20 weichen CHEN */ public class Test { public static void main

Python實現字串公共序列的演算法

        前幾天用C++實現了求兩個字串的最長公共子序列的演算法,並對演算法進行了優化,現在將該演算法用Python重新實現,基本思路C++版本是一致的。參見:求兩字串的最長公共子序列——動態規劃         1.其中需要注意幾個細節:         (1)P

給出字串,找到公共,並返回其長度,java實現

給出兩個字串,找到最長公共子串,並返回其長度。 您在真實的面試中是否遇到過這個題? Yes 樣例 給出A=“ABCD”,B=“CBCE”,返回 2 注意 子串的字元應該連續的出現在原字串中,這

字串匹配

給定兩個字串,例如 abceafg 和bcaedeafgabcea,求出它們兩個最大的公有字串,此題的解為最大長度是5,abcea。 程式碼如下: #include<iostream>

任意字串相同

c語言# include<stdio.h> #include<string.h> int main(){ char a[100],b[100]; printf("s1="); scanf("%s",a); printf("s2="); s

公共字串公共(C++)

思路: 1.按兩字串長度,兩層迴圈 2.每一次迴圈找出潛在的公共字串 (比較笨的方法,但比較好用,也很清楚,程式碼如下) #include<iostream> #include<stdio.h> #include<algorithm>

《程式設計師程式碼面試指南》字串公共

/** * 題目: * 給定兩個字串 str1 和 str2,返回兩個字串的最長公共子串。 *舉例: * str1 = "1AB2345CD",str2 = "12345EF",返回"2345"。 */ /** * 解答: * 經典動態規劃的方法可以做到時間複