检查字符串C是否是A和B的交错

时间:2013-09-06 18:08:44

标签: java string algorithm

给出三个字符串A,B和C.编写一个函数,检查C是否是A和B的交织。如果C包含A和B的所有字符以及所有字符的顺序,则称其为交错A和B.保留单个字符串中的字符。

例如:

  • 'hotdog'是'hot'和'dog'(easy)
  • 的交错
  • 'superb'是'up'和'serb'
  • 的交错
  • 'heartache'是'ear'和'ache'的交错
  • 'chat'是'hat'和'cat'
  • 的交错
  • '作弊者'是'chat'和'seer'的交错,因为虽然它包含了每个字母的所有字母,但'seer'中的字母不按顺序出现

我在net找到了一些解决方案,但下面是我的方法,有人可以告诉我,我错过了什么或我的算法会有效吗?谢谢。

我的Algo:

  1. 遍历ac。在遍历时,我们首先计算两件事:char是否存在并保存索引,即找到char的索引f。一旦我们找到了char,我们应该在那个地方添加一些特殊的char,这样我们就不会再考虑这个char了。
  2. 对于a中的c中的下一个字符,搜索您找到上一个字符的索引f,即b。如果我们找不到回报。
  3. false相同。
  4. 如果在执行上述步骤后,如果我们找到b而不是重复a而不是a = xxy, b = xxz and c = xxzxxxy 并返回结果。
  5. e.g。

    a
      

    以:

    开头      
        
    1. for a in a,c = 0xzxxxy(我将0作为特殊字符)
    2.   
    3. 对于x中的x,从索引0开始(因为我们在0处找到了前一个char)c = 00zxxxy。
    4.   
    5. for a in a,c = 00zxxx0
    6.   
    7. for b in b,c = 00z0xx0
    8.   
    9. 表示b中的x,c = 00z00x0
    10.   
    11. 对于b中的z,我们在索引4之后找不到z,索引4是我们找到b的前一个字符的索引。
    12.         

      {{1}} 开始返回false,因此我们现在将从 b 开始。

           

      首先从b:

      开始      
          
      1. for b in b,c = 0xzxxxy
      2.   
      3. for b in b,c = 00zxxxy
      4.   
      5. for b in b,c = 000xxxy
      6.   
      7. for a in a,c = 0000xxy
      8.   
      9. for a in a,c = 00000xy
      10.   
      11. 表示y,c = 00000x0
      12.   

    因此,true ie.c是a和b的交错字符串。

3 个答案:

答案 0 :(得分:9)

您的解决方案代表greedy algorithm略有修改,因为它会将C中的字符计为第一次传递中的A(或B上的A = xxyxxy B = xxzxxz C = xxzxxyxxyxxz 第二次通过)一旦找到匹配。这会破坏以下字符串:

A

作为C成员的匹配字符的第一次传递会将00zxx0000xxz 变为

B

将匹配字符计为C成员的第二个字段会将00000yxxyxx0 变为

private static boolean checkOverlap(String a, String b, String c) {
    Boolean[][][] memoize = new Boolean[a.length()+1][b.length()+1][c.length()+1];
    return checkOverlap(a, b, c, 0, 0, 0, memoize);
}
private static boolean checkOverlap(
    String a
,   String b
,   String c
,   int pa
,   int pb
,   int pc
,   Boolean[][][] memoize
) {
    Boolean res = memoize[pa][pb][pc];
    if (res != null) {
        return (boolean)res;
    }
    if (pa == a.length() && pb == b.length() && pc == c.length()) {
        res = true;
    } else if (pc == c.length()) {
        res = false;
    } else {
        res = false;
        if (pa != a.length() && c.charAt(pc) == a.charAt(pa) && checkOverlap(a, b, c, pa+1, pb, pc+1, memoize)) {
            res = true;
        } else if (pb != b.length() && c.charAt(pc) == b.charAt(pb) && checkOverlap(a, b, c, pa, pb+1, pc+1, memoize)) {
            res = true;
        }
    }
    return (memoize[pa][pb][pc] = res);
}

以下是memoized解决方案的简单Java实现:

{{1}}

Demo on ideone.

答案 1 :(得分:0)

首先,我会检查A的长度和B的长度总和等于C的长度。

接下来,检查A的第一个字符是否等于C的第一个字符。

如果没有,检查B的第一个字符是否等于C的第一个字符。

检查以A或B开头的其他字符,具体取决于上述两个条件中的哪一个为真。

这是一个可以进行测试的方法:

public boolean isInterleaved(String a, String b, String c) {
    int aIndex = 0;
    int bIndex = 0;
    int cIndex = 0;
    while (cIndex < c.length()) {
        if (aIndex < a.length()) {
            if (a.charAt(aIndex) != c.charAt(cIndex)) { return false; }
            cIndex++;
            aIndex++;
        }
        if (bIndex < b.length()) { 
            if (b.charAt(bIndex) != c.charAt(cIndex)) { return false; }
            cIndex++;
            bIndex++;
        }
    }

    return true;
}

您最多可以调用此方法两次。电话会是

if (isInterleaved(a, b, c))

if (isInterleaved(b, a, c))

如果A的第一个字符和B的第一个字符相等,请检查以上一步中没有开头的A或B字符串开头的其他字符。

这样,您可以保存可能满足条件的字符串的复杂测试。

答案 2 :(得分:0)

def isinterleave(a, b, c):
   la = len(a)
   lb = len(b)
   lc = len(c)
   if la + lb != lc: return False
   if la == lb == lc == 0: return True
   if (la > 0 and lb >0 and a[0] == b[0] == c[0]):
     return isinterleave(a[1:], b, c[1:]) or isinterleave(a, b[1:], c[1:])
   if (la > 0 and a[0] == c[0]):
     return isinterleave(a[1:], b, c[1:])
   if (lb > 0 and b[0] == c[0]):
     return isinterleave(a, b[1:], c[1:])
   return False