1. 程式人生 > >最長公共子字串

最長公共子字串

題目原意為:給出兩個字串,求出這樣的一 個最長的公共子序列的長度:子序列 中的每個字元都能在兩個原串中找到, 而且每個字元的先後順序和原串中的 先後順序一致。

遞推原則:對於S1字串第i個位置之前的子字串,和S2字串第j個位置之前的子字串,這兩者之間公共子字串的長度取決於第i-1個位置和第j-1個位置上的字元是否相等,若相等,則長度可更新為Max_len(i-1,j-1)+1; 如果這兩個位置上的字元不相等,則將i向前推一位,即Max_len(i-1,j),或將j往前推一位,即Max_len(i,j-1),比較這兩個Max_len之間的大小關係,來得到Max_len的值。注意:這裡通過這樣的比較方式得出Max_len(i,j)的值,在其後面不需要+1,因為是根據之前已經確定的子字串長度來推出目標位置的子字串,目標位置並沒有新的公共字元增加,因此不需要在後面+1!

為了節約空間和運算時間,定義一個數組用以儲存每一對index位置上對應的公共字元的個數,這樣當下一對index需要訪問時就可以隨時取用而不用重複計算

程式碼實現如下

package Dynamic_P;

import java.util.Scanner;

public class Max_subLine {
	public static void main(String args[]) {
		Scanner scan=new Scanner(System.in);
		char []ch1=scan.nextLine().toCharArray();
		char []ch2=scan.nextLine().toCharArray();
		
		int len1=ch1.length;
		int len2=ch2.length;
		int [][]Max_len=new int[len1+1][len2+1];
		
		//當S1為0或S2為0時,這兩個字串之間的公共長度為0
		for(int i=0;i<=len1;i++)
			Max_len[i][0]=0;
		for(int i=0;i<=len2;i++)
			Max_len[0][i]=0;
		
		//在這個迴圈遍歷的部分,相當於每一次固定S1字串中的某一個長度,再依次增長S2固定的長度,
		//由於這兩個長度之間的公共字元的個數都是由之前更短的S1字串或者S2字串得來的,就會直接更新相應的Max_len陣列中的值
		for(int i=1;i<=len1;i++) {
			for(int j=1;j<=len2;j++) {
				if(ch1[i-1]==ch2[j-1])
					Max_len[i][j]=Max_len[i-1][j-1]+1;
				else
					Max_len[i][j]=Math.max(Max_len[i-1][j], Max_len[i][j-1]);
			}
		}
		System.out.println(Max_len[len1][len2]);
	}
	
}