Sofia and Strings (Codeforces 1898E)
Tags: Greedy, two pointers

Sofia has a string $$$s$$$ of length $$$n$$$, consisting only of lowercase English letters. She can perform operations of the following types with this string.  Select an index $$$1 \le i \le |s|$$$ and remove the character $$$s_i$$$ from the string.  Select a pair of indices $$$(l, r)$$$ ($$$1 \le l \le r \le |s|$$$) and sort the substring $$$s_{l} s_{l+1} \ldots s_r$$$ in alphabetical order.  Here, $$$|s|$$$ denotes the current length of $$$s$$$. In particular, $$$|s| = n$$$ before the first operation. For example, if $$$s = \mathtt{sofia}$$$, then performing the operation of the first type with $$$i=4$$$ results in $$$s$$$ becoming $$$\mathtt{sofa}$$$, and performing the operation of the second type with $$$(l, r) = (2, 4)$$$ after that results in $$$s$$$ becoming $$$\mathtt{safo}$$$.Sofia wants to obtain the string $$$t$$$ of length $$$m$$$ after performing zero or more operations on string $$$s$$$ as described above. Please determine whether it is possible or not.

Input: The first line contains one integer $$$t$$$ ($$$1 \leq t \leq 10\,000$$$) — the number of test cases.The first line of each test case contains two integers $$$n$$$, $$$m$$$ ($$$1\leq m \leq n \leq 2\cdot 10^5$$$) — the lengths of string $$$s$$$ and $$$t$$$, respectively.The second line of each test case contains the string $$$s$$$ of length $$$n$$$, consisting only of lowercase English letters.The third line of each test case contains the string $$$t$$$ of length $$$m$$$, consisting only of lowercase English letters.It is guaranteed that the sum of $$$n$$$ over all test cases does not exceed $$$2\cdot 10^5$$$.

Output: For each test case, output "YES" if Sofia can obtain the string $$$t$$$ from $$$s$$$ using the operations above. Otherwise, output "NO".You can output the answer in any case (upper or lower). For example, the strings "yEs", "yes", "Yes", and "YES" will be recognized as positive responses.

Note: In the first test case, Sofia can perform the following operation:   operation of the second type with $$$l=1$$$ and $$$r=5$$$: string $$$s$$$ becomes $$$\mathtt{afios}$$$ after it. In the second test case, Sofia can perform the following operations:   operation of the second type with $$$l=1$$$ and $$$r=2$$$: string $$$s$$$ becomes $$$\mathtt{bca}$$$ after it;  operation of the first type with $$$i=3$$$: string $$$s$$$ becomes $$$\mathtt{bc}$$$ after it. In the third test case, it can be shown that it is impossible to obtain $$$t$$$ from $$$s$$$ using the provided operations.

Sample Inputs:
8
5 5
sofia
afios
3 2
cba
bc
5 1
sofia
e
15 7
anavolimilovana
aamanan
26 4
abcdefghijklmnopqrstuvwxyz
nope
26 4
zyxwvutsrqponmlkjihgfedcba
nope
7 3
apricot
cat
3 3
cba
acb

Sample Outputs:
YES
YES
NO
YES
NO
YES
NO
YES

Solution (Python):
def solve():
    (n, m) = map(int, input().split())
    a = input()
    b = input()
    V = [[] for _ in range(26)]
    for i in range(26):
        V[i].clear()
    for i in range(n, 0, -1):
        V[ord(a[i - 1]) - ord('a')].append(i)
    for i in range(1, m + 1):
        u = ord(b[i - 1]) - ord('a')
        if not V[u]:
            print('NO')
            return
        now = V[u].pop()
        for v in range(u):
            while V[v] and V[v][-1] < now:
                V[v].pop()
    print('YES')
t = int(input())
for _ in range(t):
    solve()

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

def readList():
    return list(map(int, input().split()))

def readInt():
    return int(input())

def readInts():
    return map(int, input().split())

def readStr():
    return input().strip()

def solve():
    (n, m) = readInts()
    (s, t) = ([ord(c) - ord('a') for c in readStr()], [ord(c) - ord('a') for c in readStr()])
    idx = [[] for _ in range(26)]
    for i in range(n - 1, -1, -1):
        idx[s[i]].append(i)
    for v in t:
        if not idx[v]:
            return 'NO'
        for k in range(v):
            while idx[k] and idx[k][-1] < idx[v][-1]:
                idx[k].pop()
        idx[v].pop()
    return 'YES'
for _ in range(int(input())):
    print(solve())

Solution (Python):
for _ in range(int(input())):
    (n, m) = [int(i) for i in input().split()]
    s = input()
    t = input()
    tm = [[] for _ in range(26)]
    for i in range(n - 1, -1, -1):
        tm[ord(s[i]) - 97].append(i)
    ans = 'YES'
    for i in range(m):
        v = ord(t[i]) - 97
        if not tm[v]:
            ans = 'NO'
            break
        else:
            tp = tm[v].pop()
            for j in range(0, v):
                while tm[j] and tm[j][-1] < tp:
                    tm[j].pop()
    print(ans)