Text Editor (Codeforces 1701E)
Tags: Greedy, strings

You wanted to write a text $$$t$$$ consisting of $$$m$$$ lowercase Latin letters. But instead, you have written a text $$$s$$$ consisting of $$$n$$$ lowercase Latin letters, and now you want to fix it by obtaining the text $$$t$$$ from the text $$$s$$$.Initially, the cursor of your text editor is at the end of the text $$$s$$$ (after its last character). In one move, you can do one of the following actions:  press the "left" button, so the cursor is moved to the left by one position (or does nothing if it is pointing at the beginning of the text, i. e. before its first character);  press the "right" button, so the cursor is moved to the right by one position (or does nothing if it is pointing at the end of the text, i. e. after its last character);  press the "home" button, so the cursor is moved to the beginning of the text (before the first character of the text);  press the "end" button, so the cursor is moved to the end of the text (after the last character of the text);  press the "backspace" button, so the character before the cursor is removed from the text (if there is no such character, nothing happens). Your task is to calculate the minimum number of moves required to obtain the text $$$t$$$ from the text $$$s$$$ using the given set of actions, or determine it is impossible to obtain the text $$$t$$$ from the text $$$s$$$.You have to answer $$$T$$$ independent test cases.

Input: The first line of the input contains one integer $$$T$$$ ($$$1 \le T \le 5000$$$) — the number of test cases. Then $$$T$$$ test cases follow.The first line of the test case contains two integers $$$n$$$ and $$$m$$$ ($$$1 \le m \le n \le 5000$$$) — the length of $$$s$$$ and the length of $$$t$$$, respectively.The second line of the test case contains the string $$$s$$$ consisting of $$$n$$$ lowercase Latin letters.The third line of the test case contains the string $$$t$$$ consisting of $$$m$$$ lowercase Latin letters.It is guaranteed that the sum of $$$n$$$ over all test cases does not exceed $$$5000$$$ ($$$\sum n \le 5000$$$).

Output: For each test case, print one integer — the minimum number of moves required to obtain the text $$$t$$$ from the text $$$s$$$ using the given set of actions, or -1 if it is impossible to obtain the text $$$t$$$ from the text $$$s$$$ in the given test case.


Sample Inputs:
6
9 4
aaaaaaaaa
aaaa
7 3
abacaba
aaa
5 4
aabcd
abcd
4 2
abba
bb
6 4
baraka
baka
8 7
question
problem

Sample Outputs:
5
6
3
4
4
-1

Solution (Python):
def solve():
    (n, m) = map(int, input().split())
    a = ' ' + input()
    b = ' ' + input()
    lf = [0] * (m + 2)
    for j in range(1, m + 1):
        lf[j] = lf[j - 1] + 1
        while lf[j] <= n and b[j] != a[lf[j]]:
            lf[j] += 1
        if lf[j] > n:
            print(-1)
            return
    rf = [n + 1] * (m + 2)
    for j in range(m, 0, -1):
        rf[j] = rf[j + 1] - 1
        while rf[j] >= 1 and b[j] != a[rf[j]]:
            rf[j] -= 1
        if rf[j] < 1:
            print(-1)
            return
    ans = n
    dp = [[0] * (m + 2) for _ in range(n + 2)]
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if a[i] == b[j]:
                dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1)
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if lf[j] > i:
                continue
            if rf[j + 1] <= i:
                continue
            ans = min(ans, n - i + 1 + (i - j + (i - dp[i][j])))
            if i == j:
                ans = min(ans, n - i)
    print(ans)
if __name__ == '__main__':
    t = int(input())
    for _ in range(t):
        solve()

Solution (Python):
import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def z_algorithm(w):
    m = len(w)
    z = [0] * m
    z[0] = m
    (i, j) = (1, 0)
    while i < m:
        while i + j < m and w[j] == w[i + j]:
            j += 1
        z[i] = j
        if not j:
            i += 1
            continue
        l = 1
        while l < j and l + z[l] < j:
            z[i + l] = z[l]
            l += 1
        i += l
        j -= l
    return z
q = int(input())
ans = []
inf = pow(10, 9) + 1
for _ in range(q):
    (n, m) = map(int, input().split())
    s = list(input().rstrip())
    t = list(input().rstrip())
    x = [m] * (n + 1)
    j = m
    for i in range(n - 1, -1, -1):
        if j > 0 and s[i] == t[j - 1]:
            j -= 1
        x[i] = j
    ans0 = inf
    u = 0
    for l in range(m):
        z = z_algorithm(t[l:] + s)
        for i in range(u, n):
            c = min(z[i + m - l], m - l)
            if not x[i + c] <= l + c:
                continue
            ans0 = min(ans0, i + n + 1 - l - c)
        while u < n and s[u] ^ t[l]:
            u += 1
        u += 1
    if ans0 ^ inf:
        ans0 = min(ans0, n)
        for i in range(m):
            if s[i] ^ t[i]:
                break
            ans0 = min(ans0, n - i - 1)
    ans0 = (ans0 + 1) % (inf + 1) - 1
    ans.append(ans0)
sys.stdout.write('\n'.join(map(str, ans)))

Solution (Python):
import sys
input = lambda : sys.stdin.readline().rstrip()

def solve():
    (N, M) = map(int, input().split())
    subtext = input()
    text = input()
    match_from_left = [0] * N
    j = 0
    for i in range(N):
        if subtext[i] == text[j]:
            match_from_left[i] = 1
            j += 1
        if j == M:
            break
    if j < M:
        return -1
    ans = N
    matches_so_far = 0
    for i in range(N - 1, -1, -1):
        j = M - 1 - matches_so_far
        k = i
        while j >= 0 and subtext[k] == text[j]:
            j -= 1
            k -= 1
        moves = N - 1 - i
        if k >= 0:
            moves += 2 + k + i + 1 - (M - matches_so_far)
        ans = min(ans, moves)
        if match_from_left[i] == 1:
            matches_so_far += 1
    return ans
for _ in range(int(input())):
    print(solve())