对于三个字符串A,B,C。我们称C由A和B交错组成当且仅当C包含且仅包含A,B中所有字符,且对应的顺序不改变。请编写一个高效算法,判断C串是否由A和B交错组成。
给定三个字符串A,B和C,及他们的长度。请返回一个bool值,代表C是否由A和B交错组成。保证三个串的长度均小于等于100。
测试样例:
"ABC",3,"12C",3,"A12BCC",6
返回:true
import java.util.*;
public class Mixture {
public boolean chkMixture(String A, int n, String B, int m, String C, int v) {
if(n + m != v) return false;
boolean[][] dp = new boolean[n + 1][m + 1];
dp[0][0] = true;
for (int i = 1; i <= n; i ++) {
if(A.charAt(i - 1) == C.charAt(i - 1)) dp[i][0] = true;
else break;
}
for (int j = 1; j <= m; j ++) {
if(B.charAt(j - 1) == C.charAt(j - 1)) dp[0][j] = true;
else break;
}
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
dp[i][j] = (A.charAt(i - 1) == C.charAt(i + j - 1) && dp[i - 1][j]) || (B.charAt(j - 1) == C.charAt(i + j - 1) && dp[i][j - 1]);
}
}
return dp[n][m];
}
}
import java.util.*;
public class Mixture {
public boolean chkMixture(String A, int n, String B, int m, String C, int v) {
// write code here
boolean[][] dp = new boolean[n + 1][m + 1];
dp[0][0] = true;
for(int i = 0; i <= n; ++i) {
for(int j = 0; j <= m; ++j) {
if(dp[i][j]) {
if(i < n && A.charAt(i) == C.charAt(i + j)) {
dp[i + 1][j] = true;
}
if(j < m && B.charAt(j) == C.charAt(i + j)) {
dp[i][j + 1] = true;
}
}
}
}
return dp[n][m];
}
}
import java.util.*;
public class Mixture {
public boolean chkMixture(String A, int n, String B, int m, String C, int v) {
// write code here
char[] a = A.toCharArray();
char[] b = B.toCharArray();
char[] c = C.toCharArray();
boolean[][] dp = new boolean[a.length + 1][b.length + 1];
dp[0][0] = true;
for (int i = 1; i <= a.length; ++i) {
if (a[i - 1] == c[i - 1]) {
dp[i][0] = true;
} else {
break;
}
}
for (int j = 1; j <= b.length; ++j) {
if (b[j - 1] == c[j - 1]) {
dp[0][j] = true;
} else {
break;
}
}
for (int i = 1; i <= a.length; ++i) {
for (int j = 1; j <= b.length; ++j) {
if (dp[i - 1][j] && c[i + j - 1] == a[i - 1]) {
dp[i][j] = true;
continue;
}
if (dp[i][j - 1] && c[i + j - 1] == b[j - 1]) {
dp[i][j] = true;
}
}
}
return dp[a.length][b.length];
}
}
//递归求解
class Mixture {
public:
bool chkMixture(string A, int n, string B, int m, string C, int v) {
if(n+m!=v)
return false;
if((m==0&&A==C)||(n==0&&B==C))
return true;
if((m==0&&A!=C)||(n==0&&B!=C))
return false;
if(A[0]==C[0]&&B[0]!=C[0])
return chkMixture(A.substr(1),n-1,B,m,C.substr(1),v-1);
else if(A[0]!=C[0]&&B[0]==C[0])
return chkMixture(A,n,B.substr(1),m-1,C.substr(1),v-1);
else if(A[0]==C[0]&&B[0]==C[0])
return chkMixture(A.substr(1),n-1,B,m,C.substr(1),v-1)||chkMixture(A,n,B.substr(1),m-1,C.substr(1),v-1);
else
return false;
}
};
动态规划就是从中间截断,然后从后往前看,从前往后算。
<- <-
A|BC 12|C
^ <--- ^
i A12|BCC j
^
i+j-1 定义状态:
C字符串的前i+j-1个字符可由A字符串的前i个字符和B字符串的前j个字符交错组成。
f[i][j] 表示C字符串的前i+j-1个字符能否由A字符串的前i个字符和B字符串的前j个字符交错组成,值为true或false。
再向前找出此状态所依赖的状态:
f[i][j]可以由f[i-1][j]和cc[i+j-1]==aa[i-1]组成,也可以由f[i][j-1]和cc[i+j-1]==bb[i-1]组成
f[i][j]=(f[i-1][j]&&cc[i+j-1]==aa[i-1])||(f[i][j-1]&&cc[i+j-1]==bb[i-1])
初始化
f[0][0]表示A,B两个为空串时,所能组成的C也为空串,值为true。
f[0][j]和f[i][0]表示A或B其中之一为空串时,C串仅由其中一个串组成,只需考虑依赖状态的对应一种即可。
public static boolean chkMixture(String A, int n, String B, int m, String C, int v) {
if(n+m!=v) return false;
char[] aa = A.toCharArray();
char[] bb = B.toCharArray();
char[] cc = C.toCharArray();
boolean[][] f= new boolean[n+1][m+1];
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
if(i==0&&j==0) f[i][j]=true;
else if(i==0&&j!=0){
f[i][j]=(f[i][j-1] && bb[j-1]==cc[i+j-1]);
}else if(i!=0&&j==0){
f[i][j]=(f[i-1][j] && aa[i-1]==cc[i+j-1]);
}else{
f[i][j]=((f[i][j-1] && bb[j-1]==cc[i+j-1])||(f[i-1][j] && aa[i-1]==cc[i+j-1]));
}
}
}
return f[n][m];
}
# -*- coding:utf-8 -*- class Mixture: def chkMixture(self, A, n, B, m, C, v): if self.check(A, B, C): return True return False def check(self, A, B, C): if A == C or B == C: return True if A[0] == C[0] and self.check(A[1:], B, C[1:]): return True if B[0] == C[0] and self.check(A, B[1:], C[1:]): return True return False
class Mixture {
public:
bool chkMixture(string A, int n, string B, int m, string C, int v) {
bool dp[n+1][m+1];
memset(dp,false,sizeof(dp));
dp[0][0] = true;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
if(dp[i][j]) { if(i<n && A[i]==C[i+j]) dp[i+1][j] = true; if(j<m && B[j]==C[i+j]) dp[i][j+1] = true; } return dp[n][m];
}
};
#递归版本
if n == 0 or m == 0 or v == 0:
return True
if A[0] == C[0] and B[0] != C[0]:
return self.chkMixture(A[1:], n-1, B, m, C[1:], v-1)
if B[0] == C[0] and A[0] != C[0]:
return self.chkMixture(A, n, B[1:], m-1, C[1:], v-1)
if A[0] == C[0] == B[0]:
return self.chkMixture(A[1:], n-1, B, m, C[1:], v-1) or self.chkMixture(A, n, B[1:], m-1, C[1:], v-1)
return False
#动态规划版本 class Mixture:
def chkMixture(self, A, n, B, m, C, v):
# write code here
dp = [[False for i in range(m+1)] for j in range(n+1)]
for i in range(n+1):
for j in range(m+1):
if i == j == 0:
dp[i][j] = True
elif i == 0 and j != 0:
dp[i][j] = dp[i][j-1] and B[j-1] == C[j-1]
elif i != 0 and j == 0:
dp[i][j] = dp[i-1][j] and A[i-1] == C[i-1]
elif A[i-1] == C[i+j-1] and dp[i-1][j] == True:
dp[i][j] = True
elif B[j-1] == C[i+j-1] and dp[i][j-1] == True:
dp[i][j] = True
return dp[-1][-1]
package alex.suda.dp;
import java.util.Scanner;
public class test5 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
String A = scanner.next();
int m = scanner.nextInt();
String B = scanner.next();
int v = scanner.nextInt();
String C = scanner.next();
System.out.print(chkMixture(A, n, B, m, C, v));
}
}
public static boolean chkMixture(String A, int n, String B, int m, String C, int v) {
// d[i][j]表示当A在i位处是交错的同时s2在j位处是交错的s3在i+j处是否是交错的。
// 如果A和B在当前位置是空,C也是空,为true
// 如果A为空,B之前的位置是交错的而且s2在当前位置和s3的当前位置字符是一样的,则视为true;反之s2为空时情况是一样的。
// A和B都不为空,从i-1,j到达i,j处时,如果i-1,j处是交错的而i处与当前的s3一致,则视为true;
// 当我们从i,j-1到达i,j处时,如果i,j-1处是交错的而j处与当前的s3一致,则视为true;
boolean[][] d = new boolean[n + 1][m + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
if (i == 0 && j == 0) {
d[i][j] = true;
} else if (i == 0) {
d[i][j] = (d[i][j - 1] && B.charAt(j - 1) == C.charAt(i + j - 1));
} else if (j == 0) {
d[i][j] = (d[i - 1][j] && A.charAt(i - 1) == C.charAt(i + j - 1));
} else {
d[i][j] = (d[i - 1][j] && A.charAt(i - 1) == C.charAt(i + j - 1))
|| (d[i][j - 1] && B.charAt(j - 1) == C.charAt(i + j - 1));
}
}
}
return d[n][m];
}
}
bool chkMixture(string A, int n, string B, int m, string C, int v) {
// write code here
if((n+m) != v)
return false;
if(!v)
return true;
if(n==v && A==C)
return true;
else if(n==v)
return false;
if(m==v && B==C)
return true;
else if(m==v)
return false;
vector<vector<bool> > c(n+1, vector<bool>(m+1, false));
c[0][0] = true;
for(int i = 1; i <= n; ++i)
if(A[i-1] == C[i-1])
c[i][0] = c[i-1][0];
for(int i = 1; i <=m; ++i)
if(B[i-1] == C[i-1])
c[0][i] = c[0][i-1];
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
if(!c[i][j] && A[i-1] == C[i+j-1])
c[i][j] = c[i-1][j];
if(!c[i][j] && B[j-1] == C[i+j-1])
c[i][j] = c[i][j-1];
}
}
return c[n][m];
}
"ABC","12C","A12BCC"就比如这题的示例,我们假如比较到了BCC中的B,我们判断这个时候true或者false的时候,我们需要知道的是前面A12的比较情况,我们就可以把dp[][]中前一次的情况取出来再加上这一次的比较结果在写入新的dp当中,知道我们目标字符串遍历完毕即可。
class Mixture {public:bool chkMixture(string A, int n, string B, int m, string C, int v) {// write code hereif(n+m!=v)return false;vector<vector<bool>> dp (n+1,vector<bool>(m+1,false));int a=0;int b=0;dp[0][0] = true;for(int i=0;i<v;i++){if(A[a] == C[i] && dp[a][b] == true){a++;dp[a][b] = true;}if(B[b] == C[i] && dp[a][b] == true){b++;dp[a][b] = true;}}return dp[n][m];}};
#这题测试用例应该不完备
#下面算法的思想就是:先比较A是否包含在C中,再比较B是否包含在C中,完全没使用到动态规划
class Mixture:
def chkMixture(self, A, n, B, m, C, v):
# write code here
flag_A = True
flag_B = True
i = 0
j = 0
#先比较A是否包含在C中
while i < n and j < v:
if A[i] == C[j]:
i += 1
j += 1
#当j已遍历玩C,但是A数组中还有字符未在C中找到时,返回FALSE
if i < n and j >= v:
flag_A = False
break
i = 0
j = 0
#再比较B是否包含在C中
while i < m and j < v:
if B[i] == C[j]:
i += 1
j += 1
if i < m and j >= v:
flag_B = False
break
return (flag_A and flag_B) python递归解法,通过了所有测试,不过还是不如DP解法。。先放上去,大家可以参考一下:
class Mixture:
def chkMixture(self, A, n, B, m, C, v):
# write code here
if not n+m==v:
return False
self.canForm=False
self.dfs(A,B,C)
return self.canForm
def dfs(self, s1, s2, s3):
if self.canForm:
return
if s3 == "":
self.canForm = True
return
if s1 and s1[0] == s3[0]:
self.dfs(s1[1:], s2, s3[1:])
if s2 and s2[0] == s3[0]:
self.dfs(s1, s2[1:], s3[1:])
public boolean chkMixture(String str1, int n, String str2, int m, String aim, int v) {
if (str1 == null || str2 == null || aim == null)
return false;
char[] ch1 = str1.toCharArray();
char[] ch2 = str2.toCharArray();
char[] chaim = aim.toCharArray();
if (m + n != v)
return false;
boolean[][] dp = new boolean[n + 1][m + 1];
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
if (dp[i - 1][0] && ch1[i - 1] == chaim[i - 1])
dp[i][0] = true;
}
for (int j = 1; j <= m; j++) {
if (dp[0][j-1] && ch2[j - 1] == chaim[j - 1])
dp[0][j] = true;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if ((dp[i - 1][j] && ch1[i - 1] == chaim[i + j - 1])
|| (dp[i][j - 1] && ch2[j - 1] == chaim[i + j - 1]))
dp[i][j] = true;
}
}
return dp[n][m];
}
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String str1=input.next();
int num1=input.nextInt();
String str2=input.next();
int num2=input.nextInt();
String str3=input.next();
int num3=input.nextInt();
boolean flag;
if(num1+num2==num3){
flag=isContain(str1,str2,str3);
//flag=isContain2(str1,str2,str3,num1,num2,num3);
}
else flag=false;
System.out.println(flag);
}
public static boolean isContain(String str1,String str2, String str3){
return process(str1,str2,str3,0,0,0);
}
public static boolean process(String str1,String str2,String str3,int index1,int index2,int index3){
if(index3>=str3.length()) return true;
boolean flag1=false,flag2=false;
if(index1<str1.length() && str1.charAt(index1)==str3.charAt(index3)){
flag1=process(str1,str2,str3,index1+1,index2,index3+1);
}
if(index2<str2.length() && str2.charAt(index2)==str3.charAt(index3)){
flag2=process(str1,str2,str3,index1,index2+1,index3+1);
}
return flag2||flag2;
} public boolean chkMixture(String str1, int n, String str2, int m, String str3, int v) {
if(n+m!=v) return false;
boolean[][] dp=new boolean[n+1][m+1];
dp[n][m]=true;
for (int i = n-1; i >=0 ; i--) {
dp[i][m]=str1.charAt(i)==str3.charAt(i+m)? dp[i+1][m]:false;
}
for (int i = m-1; i >=0 ; i--) {
dp[n][i]=str2.charAt(i)==str3.charAt(i+n)? dp[n][i+1]:false;
}
for (int i = n-1; i >=0 ; i--) {
for (int j = m-1; j >=0 ; j--) {
boolean flag1=false,flag2=false;
if(str1.charAt(i)==str3.charAt(i+j)) flag1=dp[i+1][j];
if(str2.charAt(j)==str3.charAt(i+j)) flag2=dp[i][j+1];
dp[i][j]=flag1||flag2;
}
}
return dp[0][0];
} class Mixture:
def chkMixture(self, A, n, B, m, C, v):
pointerA = 0
pointerB = 0
if n+m == v:
for i in range(v):
if pointerA < n and C[i] == A[pointerA]:
pointerA += 1
elif pointerB < m and C[i] == B[pointerB]:
pointerB += 1
else:
return False
return True
else:
return False
if __name__ == "__main__":
A, n, B, m, C, v = eval("["+input().strip()+"]")
print(Mixture().chkMixture(A, n, B, m, C, v)) class Mixture {
public:
bool chkMixture(string A, int n, string B, int m, string C, int v) {
if (v != n + m) {
return false;
}
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
if (dp[i - 1][0] && A[i - 1] == C[i - 1]) {
dp[i][0] = true;
}
}
for (int j = 1; j <= m; j++) {
if (dp[0][j - 1] && B[j - 1] == C[j - 1]) {
dp[0][j] = true;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = (dp[i - 1][j] && C[i + j - 1] == A[i - 1])
|| (dp[i][j - 1] && C[i + j - 1] == B[j - 1]);
}
}
return dp[n][m];
}
};
# -*- coding:utf-8 -*- class Mixture: def chkMixture(self, A, n, B, m, C, v): if n == 0 or m == 0 or v == 0:#ABC中任何一个已遍历完毕,则为True return True if A[0] == C[0] and B[0] != C[0]:#C中当前首字符为A的首字符 return self.chkMixture(A[1:], n-1, B, m, C[1:], v-1) if B[0] == C[0] and A[0] != C[0]:#C中当前首字符为B的首字符 return self.chkMixture(A, n, B[1:], m-1, C[1:], v-1) if A[0] == C[0] == B[0]:#C中当前首字符可能为A的首字符,也可能为B的首字符 return self.chkMixture(A[1:], n-1, B, m, C[1:], v-1) or self.chkMixture(A, n, B[1:], m-1, C[1:], v-1)