CodeEval / Sequence Transformation Code Timeout

时间:2014-06-19 01:12:31

标签: algorithm recursion dynamic-programming

挑战说明如下:https://www.codeeval.com/browse/130/

两条规则:

  1. " 0"可以转换成非空的字母序列" A" (" A"," AA"," AAA"等)
  2. " 1"可以转换成非空的字母序列" A" (" A"," AA"," AAA"等)或非空字母序列" B" (" B"," BB"," BBB"等)例如。
  3. 测试案例:

    1. 1010 AAAAABBBBAAAA ==>是
    2. 00 AAAAAA ==>是
    3. 01001110 AAAABAAABBBBBBAAAAAAA ==>是
    4. 1100110 BBAABABBA ==>否
    5. 我想到的解决方案是正则表达式,我以递归方式实现。对于上面的小测试用例,它工作正常。但是当涉及到长字符串时,代码会超时超过10秒。

      例如,以下案例需要"永远"得到结果:

      00111010000001000111010000101111110101110001001 AAAAAAAAAAAAAAABBBBBAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAABBBBBBAAAAAAAAAAAAAAAAAAAAAABBBBAAAAAAAAAABBBBBBBBBBBBBAAAAAAAAAAABBBBBBAAAABBAAAAAAAAAAAAAAA

      还有更长的病例需要等待测试。

      以下是我的代码:

      #include <iostream>
      using namespace std;
      
      bool validate(string pattern, int i, string text, int j);
      
      bool matchA(string pattern, int i, string text, int j)
      {
          while(j < text.size() && text[j] == 'A')
          {
              j++;
              if(validate(pattern, i+1, text, j))
                  return true;
          }
          return false;
      }
      
      bool matchAB(string pattern, int i, string text, int j, char c)
      {
          while(j < text.size() && text[j] == c)
          {
              j++;
              if(validate(pattern, i+1, text, j))
                  return true;
          }
          return false;
      }
      
      bool validate(string pattern, int i, string text, int j)
      {
          if(i == pattern.size())
              return j == text.size();
          if(pattern[i] == '0')
              return matchA(pattern, i, text, j);
          if(pattern[i] == '1')
              return matchAB(pattern, i, text, j, text[j]);
          return false;
      }
      
      int main(int argc, char* argv[])
      {
          string pattern = "00";
          string text = "AAAAA";
          if(validate(pattern, 0, text, 0))
              cout << "Yes" << endl;
          else
              cout << "No" << endl;
          return 0;
      }
      

      我的问题是:

      1. 如何证明上述代码的正确性(具有讽刺意味的是,我对我写的递归不是很有信心)?
      2. 如果代码不正确,我该如何调试呢?
      3. 假设我的代码是正确的,很明显递归不是最好的解决方案(太多的回溯),我有一种感觉,通过使用DP来解决它。我已经尝试了memoization来存储(i,j)的结果,但仍然失败了。需要想法来解决这个问题。
      4. 感谢您的时间和意见!

1 个答案:

答案 0 :(得分:4)

感谢@ jonderry的提示,这是DP解决方案:

假设State [i,j]用于保存pattern [i]和text [j]的状态,如果State [i,j] == true,我们说从pattern [0]到pattern [i ]并且从文本[0]到文本[j],序列转换是有效的。 因此,我们可以根据以下条件计算State [i,j]:

State[i,j] =
1. (pattern[i] == '0' and text[j] == 'A') or pattern[i] == '1'   // if State[i-1,j-1] = true
2. State[i-1,j] && text[j-1] == text[j],                         // otherwise 

感谢您的时间和意见!