mod = 998244353 omega = pow(3,119,mod) rev_omega = pow(omega,mod-2,mod) N = 2*10**5 g1 = [1]*(N+1) # 元テーブル g2 = [1]*(N+1) #逆元テーブル inv = [1]*(N+1) #逆元テーブル計算用テーブル for i in range( 2, N + 1 ): g1[i]=( ( g1[i-1] * i ) % mod ) inv[i]=( ( -inv[mod % i] * (mod//i) ) % mod ) g2[i]=( (g2[i-1] * inv[i]) % mod ) inv[0]=0 def _ntt(f,L,reverse=False): F=[f[i] for i in range(L)] n = L.bit_length() - 1 base = omega if reverse: base = rev_omega if not n: return F size = 2**n wj = pow(base,2**22,mod) res = [0]*2**n for i in range(n,0,-1): use_omega = pow(base,2**(22+i-n),mod) res = [0]*2**n size //= 2 w = 1 for j in range(0,L//2,size): for a in range(size): res[a+j] = (F[a+2*j] + w * F[a+size+2*j]) % mod t = (w * wj) % mod res[L//2+a+j] = (F[a+2*j] + t * F[a+size+2*j]) % mod w = (w * use_omega) % mod F = res return res def ntt(f,L=0): l = len(f) if not L: L = 1<<((l-1).bit_length()) while len(f) c[i] = sum(a[j] * b[i - j] for j in range(i + 1)) % 998244353. It returns an empty list if at least one of a and b are empty. Constraints ----------- > len(a) + len(b) <= 8388609 Complexity ---------- > O(n log n), where n = len(a) + len(b). """ n = len(a) m = len(b) if n == 0 or m == 0: return [] if min(n, m) <= 0: return _convolution_naive(a, b) if a is b: return _convolution_square(a) return _convolution_fft(a, b) import sys,random,bisect from collections import deque,defaultdict from heapq import heapify,heappop,heappush from itertools import permutations from math import gcd,log input = lambda :sys.stdin.readline().rstrip() mi = lambda :map(int,input().split()) li = lambda :list(mi()) def Z_algorithm(s): N = len(s) Z_alg = [0]*N Z_alg[0] = N i = 1 j = 0 while i < N: while i+j < N and s[j] == s[i+j]: j += 1 Z_alg[i] = j if j == 0: i += 1 continue k = 1 while i+k < N and k + Z_alg[k] typing.List[int]: sa = list(range(len(s))) return sorted(sa, key=lambda i: s[i:]) def _sa_doubling(s: typing.List[int]) -> typing.List[int]: n = len(s) sa = list(range(n)) rnk = copy.deepcopy(s) tmp = [0] * n k = 1 while k < n: def cmp(x: int, y: int) -> bool: if rnk[x] != rnk[y]: return rnk[x] - rnk[y] rx = rnk[x + k] if x + k < n else -1 ry = rnk[y + k] if y + k < n else -1 return rx - ry sa.sort(key=functools.cmp_to_key(cmp)) tmp[sa[0]] = 0 for i in range(1, n): tmp[sa[i]] = tmp[sa[i - 1]] + (1 if cmp(sa[i - 1], sa[i]) else 0) tmp, rnk = rnk, tmp k *= 2 return sa def _sa_is(s: typing.List[int], upper: int) -> typing.List[int]: ''' SA-IS, linear-time suffix array construction Reference: G. Nong, S. Zhang, and W. H. Chan, Two Efficient Algorithms for Linear Time Suffix Array Construction ''' threshold_naive = 10 threshold_doubling = 40 n = len(s) if n == 0: return [] if n == 1: return [0] if n == 2: if s[0] < s[1]: return [0, 1] else: return [1, 0] if n < threshold_naive: return _sa_naive(s) if n < threshold_doubling: return _sa_doubling(s) sa = [0] * n ls = [False] * n for i in range(n - 2, -1, -1): if s[i] == s[i + 1]: ls[i] = ls[i + 1] else: ls[i] = s[i] < s[i + 1] sum_l = [0] * (upper + 1) sum_s = [0] * (upper + 1) for i in range(n): if not ls[i]: sum_s[s[i]] += 1 else: sum_l[s[i] + 1] += 1 for i in range(upper + 1): sum_s[i] += sum_l[i] if i < upper: sum_l[i + 1] += sum_s[i] def induce(lms: typing.List[int]) -> None: nonlocal sa sa = [-1] * n buf = copy.deepcopy(sum_s) for d in lms: if d == n: continue sa[buf[s[d]]] = d buf[s[d]] += 1 buf = copy.deepcopy(sum_l) sa[buf[s[n - 1]]] = n - 1 buf[s[n - 1]] += 1 for i in range(n): v = sa[i] if v >= 1 and not ls[v - 1]: sa[buf[s[v - 1]]] = v - 1 buf[s[v - 1]] += 1 buf = copy.deepcopy(sum_l) for i in range(n - 1, -1, -1): v = sa[i] if v >= 1 and ls[v - 1]: buf[s[v - 1] + 1] -= 1 sa[buf[s[v - 1] + 1]] = v - 1 lms_map = [-1] * (n + 1) m = 0 for i in range(1, n): if not ls[i - 1] and ls[i]: lms_map[i] = m m += 1 lms = [] for i in range(1, n): if not ls[i - 1] and ls[i]: lms.append(i) induce(lms) if m: sorted_lms = [] for v in sa: if lms_map[v] != -1: sorted_lms.append(v) rec_s = [0] * m rec_upper = 0 rec_s[lms_map[sorted_lms[0]]] = 0 for i in range(1, m): left = sorted_lms[i - 1] right = sorted_lms[i] if lms_map[left] + 1 < m: end_l = lms[lms_map[left] + 1] else: end_l = n if lms_map[right] + 1 < m: end_r = lms[lms_map[right] + 1] else: end_r = n same = True if end_l - left != end_r - right: same = False else: while left < end_l: if s[left] != s[right]: break left += 1 right += 1 if left == n or s[left] != s[right]: same = False if not same: rec_upper += 1 rec_s[lms_map[sorted_lms[i]]] = rec_upper rec_sa = _sa_is(rec_s, rec_upper) for i in range(m): sorted_lms[i] = lms[rec_sa[i]] induce(sorted_lms) return sa def suffix_array(s: typing.Union[str, typing.List[int]], upper: typing.Optional[int] = None) -> typing.List[int]: if isinstance(s, str): return _sa_is([ord(c) for c in s], 255) elif upper is None: n = len(s) idx = list(range(n)) idx.sort(key=functools.cmp_to_key(lambda l, r: s[l] - s[r])) s2 = [0] * n now = 0 for i in range(n): if i and s[idx[i - 1]] != s[idx[i]]: now += 1 s2[idx[i]] = now return _sa_is(s2, now) else: assert 0 <= upper for d in s: assert 0 <= d <= upper return _sa_is(s, upper) def lcp_array(s: typing.Union[str, typing.List[int]], sa: typing.List[int]) -> typing.List[int]: ''' Reference: T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park, Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its Applications ''' if isinstance(s, str): s = [ord(c) for c in s] n = len(s) assert n >= 1 rnk = [0] * n for i in range(n): rnk[sa[i]] = i lcp = [0] * (n - 1) h = 0 for i in range(n): if h > 0: h -= 1 if rnk[i] == 0: continue j = sa[rnk[i] - 1] while j + h < n and i + h < n: if s[j + h] != s[i + h]: break h += 1 lcp[rnk[i] - 1] = h return lcp def solve(N,M,S,T): Sa = S.replace("?","a") SaT = T + "#" + Sa check = Z_algorithm(SaT) for i in range(N): if check[i+M+1] == M: return Sa SaT_suffix = Sa + "#" + T X = suffix_array(SaT_suffix) pos = [-1] * (N+M+1) for i in range(N+M+1): pos[X[i]] = i """ Sの?を置き換える際は ・かならず?->a以外にするとこがある(->?を置き換える部分がある) S[i:i+M] と S[j:j+M] (i < j) の置き換えを比較するとき、 i+M < j のとき、jが小さい T[:j-i]とSa[i:j] の比較 T[j-i:M] と T[:i+M-j] の比較 Sa[i+M:j+M] と T[i+M-j:M] の比較 これで決着がつかない場合、iが小さい """ wild_cnt = [0] + [S[i]=="?" for i in range(N)] for i in range(N): wild_cnt[i+1] += wild_cnt[i] T_Z = Z_algorithm(T) def compare(i,j): if i+M <= j: return j #print(i,j,check,SaT,check[i+M+1],Sa[check[i+M+1]]) if check[i+M+1] < j-i: if T[check[i+M+1]] < Sa[i+check[i+M+1]]: return i else: return j if T_Z[j-i] < M+i-j: if T[j-i+T_Z[j-i]] > T[T_Z[j-i]]: return j else: return i if pos[i+M] < pos[N+1+i+M-j]: return i else: return j hash = [k+1 for k in range(26)] f = [0] * N for i in range(N): if S[i]!="?": f[i] = hash[ord(S[i])-ord("a")] g = [0] * M for i in range(M): if T[i]!="?": g[i] = hash[ord(T[i])-ord("a")] p = convolution([f[i]**3 % mod for i in range(N)],g[::-1]) q = convolution([f[i]**2 % mod for i in range(N)],[g[i]**2 % mod for i in range(M)][::-1]) r = convolution([f[i] % mod for i in range(N)],[g[i]**3 % mod for i in range(M)][::-1]) cand = [] for i in range(N-M+1): if (p[i+M-1]-2*q[i+M-1]+r[i+M-1]) % mod == 0: cand.append(i) #print(cand) if not cand: return -1 k = cand[0] for i in cand[1:]: k = compare(k,i) res = "".join([S[:k].replace("?","a") , T , S[k+M:].replace("?","a")]) return res def brute(N,M,S,T): res = "z" * (N+1) for i in range(N-M+1): flag = True for j in range(M): if S[i+j]!="?" and S[i+j]!=T[j]: flag = False if flag: tmp = S[:i].replace("?","a") + T + S[i+M:].replace("?","a") res = min(res,tmp) if len(res) == N + 1: return -1 else: return res while False: N = random.randint(2,20) M = random.randint(1,N) S = "".join([random.choice("abc?") for i in range(N)]) T = "".join([random.choice("abc") for i in range(M)]) if solve(N,M,S,T)!=brute(N,M,S,T): print(N,M) print(S) print(T) print(solve(N,M,S,T),brute(N,M,S,T)) break else: print("AC") for _ in range(int(input())): N,M = mi() S = input() T = input() print(solve(N,M,S,T))