How to apply a backtracking algorithm?
<p>I'm doing some excercises in Python course and one of them where I'm stuck is below:</p>

<pre><code>Given a digit sequence that represents a message where each uppercase letter 
is replaced with a number (A - 1, B - 2, ... , Z - 26) and space - 0. 
Find the number of the initial messages, from which that sequence 
could be obtained.

Example: 12345 - 3 (ABCDE, LCDE, AWDE)
         11 - 2 (AA, K)
</code></pre>

<p>The naive solution is easy and it is simple bruteforce algorithm:</p>

<pre><code>import string

def count_init_messages(sequence):
    def get_alpha(seq):
        nonlocal count

        if len(seq) == 0:
            count += 1
            return

        for i in range(1, len(seq) + 1):
            if seq[:i] not in alph_table:
                break
            else:
                get_alpha(seq[i:])

    alphabet = " " + string.ascii_uppercase
    # generate dictionary of possible digit combination
    alph_table = {str(n): alph for n, alph in zip(range(len(alphabet)), alphabet)}
    # counter for the right combination met
    count = 0
    get_alpha(sequence)

    return count

def main():
    sequence = input().rstrip()
    print(count_init_messages2(sequence))

if __name__ == "__main__":
    main()
</code></pre>

<p>But as the length of an input sequence might be as long as 100 characters and there might be lots of repetition I have met a time limits. For example, one of the sample input is <code>2222222222222222222222222222222222222222222222222222222222222222222222 (possible messages number is 308061521170129)</code>. As my implementation makes too many repetition it takes ages for processing such an input. I think of using the backtracking algorithm, but I haven't realised yet how to implement the memoization for the succesive results.</p>

<p>I'd be glad if it is possible to point me out to the right way how to break that task.</p>

<p>The recurrence relation you have to solve (where <code>s</code> is a string of digits, and <code>a</code> and <code>b</code> are single digits) is this:</p>

<pre><code> S("") = 1
 S(a) = 1
 S(s + a + b) = S(s+a) + (S(s) if ab is between 10 and 26)
</code></pre>

<p>That can be computed using dynamic programming rather than backtracking. If you do it right, it's O(n) time complexity, and O(1) space complexity.</p>

<pre><code>def seq(s):
    a1, a2 = 1, 1
    for i in xrange(1, len(s)):
        a1, a2 = a1 + (a2 if 9 &lt; int(s[i-1:i+1]) &lt; 27 else 0), a1
    return a1

print seq('2222222222222222222222222222222222222222222222222222222222222222222222')
</code></pre>

python algorithm backtracking