def can_be_interwoven(s, t, u): '''Return True if and only if the motifs t and u can be interwoven into the string s.''' nt, nu = len(t), len(u) # Allocation + initial condition at i=0. First and last column correspond to the empty motifs. # At step i in the outer loop (x=s[i]), m[j,k] = (s[0..i] ENDS with an interweaving of # t[0..j], u[0..k] can be interwoven); m_old holds m[i-1, :, :]. m, m_old = ro.zeros_bool_array(nt + 1, nu + 1), ro.zeros_bool_array(nt + 1, nu + 1) m[0][0] = -1; # m_max = m[-1][-1] # Dynamic programming - prefixes of s for x in s: ra.copy_list(m, m_old) # Initial condition - first row (j=0) for k, uk in enumerate(u, 1): m[0][k] = m_old[0][k - 1] if x == uk else 0 # Initial condition - first column (k=0) for j, tj in enumerate(t, 1): m[j][0] = m_old[j - 1][0] if x == tj else 0 # Dynamic programming - prefixes of t,u in s[0..i] vs. in s[0..i-1]. for j, tj in enumerate(t, 1): for k, uk in enumerate(u, 1): mjk = 0 if x == tj: mjk |= m_old[j - 1][ k] if x == uk: mjk |= m_old[j][k - 1] m[j][k] = mjk # Shortcut: since it's a boolean result and we are OR-ing, once it's True it # must stay True, so no need to complete the entire outer loop over s. Had we # needed an integer result, we'd have to do the maximization over all s prefixes if m[-1][-1]: return True #m_max |= m[-1][-1] #return m_max return False
def itwv_matrix(s, t): '''Return the boolean matrix M.''' # By symmetry, we only need to call can_be_interwoven() for M's upper triangular part n = len(t) m = ro.zeros_bool_array(n, n) for i, ti in enumerate(t): for j in xrange(i, n): m[i][j] = can_be_interwoven(s, ti, t[j]) m[j][i] = m[i][j] return m