DP33 两个字符串交叉得到的字符串 Find if a string is interleaved of two other strings @geeksforgeeks...

Given three strings A, B and C. Write a function that checks whether C is an interleaving of A and B.C is said to be interleaving A and B, if it contains all characters of A and B and order of all characters in individual strings is preserved.

We have discussed a simple solution of this problemhere. The simple solution doesn’t work if strings A and B have some common characters. For example A = “XXY”, string B = “XXZ” and string C = “XXZXXXY”. To handle all cases, two possibilities need to be considered.

a)If first character of C matches with first character of A, we move one character ahead in A and C and recursively check.

b)If first character of C matches with first character of B, we move one character ahead in B and C and recursively check.

If any of the above two cases is true, we return true, else false. Following is simple recursive implementation of this approach (Thanks toFredericfor suggesting this)


这是一系列的几道题:

1 判断c是否是由a和b交叉而得:

1. 递归 2 DP 3 3指针,但是当有重复字符出现时出错!

2 打印出a和b交叉而得的所有组合:递归


package DP;

public class InterleaveStrings {

	public static void main(String[] args) {
		String s1 = "AB";
		String s2 = "CD";
		printTwoInterleavings(s1, s2, "");
		String s = "ACEB";
		System.out.println(isInterleavedNaive(s1, s2, s));
		System.out.println(isInterleavedRec(s1, s2, s));
		System.out.println(isInterleavedDP(s1, s2, s));
	}
	
	
	/*
	 Input: str1 = "AB",  str2 = "CD"
	 Output:
	    ABCD
	    ACBD
	    ACDB
	    CABD
	    CADB
	    CDAB
	 */
	public static void printTwoInterleavings(String s1, String s2, String soFar){
		if(s1.length()==0 && s2.length()==0){
			System.out.println(soFar);
			return;
		}
		if(s1.length() == 0){
			System.out.println(soFar + s2);
			return;
		}
		if(s2.length() == 0){
			System.out.println(soFar + s1);
			return;
		}
		printTwoInterleavings(s1.substring(1), s2, soFar+s1.charAt(0));
		printTwoInterleavings(s1, s2.substring(1), soFar+s2.charAt(0));
	}
	
	
	
	// O(2^n)
	public static boolean isInterleavedRec(String s1, String s2, String s){
		// Base Case: If all strings are empty
		if(s1.length()==0 && s2.length()==0 && s.length()==0){
			return true;
		}
		if(s.length() == 0){		// If s is empty and any of the two strings is not empty
			return false;
		}
		
		boolean b1 = false;
		boolean b2 = false;
		
		if(s1.length()!=0 && s.charAt(0)==s1.charAt(0)){
			b1 = isInterleavedRec(s1.substring(1), s2, s.substring(1));
		}
		if(s2.length()!=0 && s.charAt(0)==s2.charAt(0)){
			b2 = isInterleavedRec(s1, s2.substring(1), s.substring(1));
		}
		
		// If any of the above mentioned two possibilities is true,
	    // then return true, otherwise false
		return b1 || b2;
	}
	
	
	// A Dynamic Programming based program to check whether a string s is
	// an interleaving of two other strings s1 and s2.
	// O(L1*L2) time, space
	public static boolean isInterleavedDP(String s1, String s2, String s){
		int L1 = s1.length();		// Find lengths of the two strings
		int L2 = s2.length();
		int L = s.length();
		
		// Let us create a 2D table to store solutions of
	    // subproblems.  isIL[i][j] will be true if s[0..i+j-1]
	    // is an interleaving of s1[0..i-1] and s2[0..j-1].
		boolean[][] isIL = new boolean[L1+1][L2+1];
		
		// C can be an interleaving of A and B only of sum
	    // of lengths of A & B is equal to length of C.
		if(L1+L2 != L){
			return false;
		}
		
		for(int l1=0; l1<=L1; l1++){
			for(int l2=0; l2<=L2; l2++){
				// two empty strings have an empty string as interleaving
				if(l1==0 && l2==0){
					isIL[l1][l2] = true;
				}
				// A is empty
				else if(l1==0 && s2.charAt(l2-1)==s.charAt(l2-1)){
					isIL[l1][l2] = isIL[l1][l2-1];
				}
				// B is empty
				else if(l2==0 && s1.charAt(l1-1)==s.charAt(l1-1)){
					isIL[l1][l2] = isIL[l1-1][l2];
				}
				
				if(l1!=0 && l2!=0){
					// Current character of C matches with current character of A,
		            // but doesn't match with current character of B
					if(s.charAt(l1+l2-1)==s1.charAt(l1-1) && s.charAt(l1+l2-1)!=s2.charAt(l2-1)){
						isIL[l1][l2] = isIL[l1-1][l2];
					}
					// Current character of C matches with current character of B,
		            // but doesn't match with current character of A
					else if(s.charAt(l1+l2-1)==s2.charAt(l2-1) && s.charAt(l1+l2-1)!=s1.charAt(l1-1)){
						isIL[l1][l2] = isIL[l1][l2-1];
					}
					// Current character of C matches with that of both A and B
					else if(s.charAt(l1+l2-1)==s1.charAt(l1-1) && s.charAt(l1+l2-1)==s2.charAt(l2-1)){
						isIL[l1][l2] = isIL[l1-1][l2] || isIL[l1][l2-1];
					}
				}
			}
		}
		
		return isIL[L1][L2];
	}
	
	
	
	
	// Time Complexity: O(m+n) where m and n are the lengths of strings A and B respectively.
	// This approach doesn’t work if A and B have some characters in common.
	// http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-interleaving-of-two-other-given-strings/
	public static boolean isInterleavedNaive(String s1, String s2, String s){
		int i=0, j=0, k=0;
		while(k != s.length()){
			if(s.charAt(k) == s1.charAt(i)){
				i++;
			}else if(s.charAt(k) == s2.charAt(j)){
				j++;
			}else{
				return false;
			}
			k++;
		}
		if(i!=s1.length() || j!=s2.length()){
			return false;
		}
		return true;
	}
	
	

}
	



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值