Your classmate, whom you do not like because he is boring, but whom you respect for his intellect, has two strings: $s$ of length $n$ and $t$ of length $m$.

A sequence $p_1, p_2, \ldots, p_m$, where $1 \leq p_1 < p_2 < \ldots < p_m \leq n$, is called beautiful, if $s_{p_i} = t_i$ for all $i$ from $1$ to $m$. The width of a sequence is defined as $\max\limits_{1 \le i < m} \left(p_{i + 1} - p_i\right)$.

Please help your classmate to identify the beautiful sequence with the maximum width. Your classmate promised you that for the given strings $s$ and $t$ there is at least one beautiful sequence.


-----Input-----

The first input line contains two integers $n$ and $m$ ($2 \leq m \leq n \leq 2 \cdot 10^5$) — the lengths of the strings $s$ and $t$.

The following line contains a single string $s$ of length $n$, consisting of lowercase letters of the Latin alphabet.

The last line contains a single string $t$ of length $m$, consisting of lowercase letters of the Latin alphabet.

It is guaranteed that there is at least one beautiful sequence for the given strings.


-----Output-----

Output one integer — the maximum width of a beautiful sequence.


-----Examples-----

Input
5 3
abbbc
abc
Output
3
Input
5 2
aaaaa
aa
Output
4
Input
5 5
abcdf
abcdf
Output
1
Input
2 2
ab
ab
Output
1


-----Note-----

In the first example there are two beautiful sequences of width $3$: they are $\{1, 2, 5\}$ and $\{1, 4, 5\}$.

In the second example the beautiful sequence with the maximum width is $\{1, 5\}$.

In the third example there is exactly one beautiful sequence — it is $\{1, 2, 3, 4, 5\}$.

In the fourth example there is exactly one beautiful sequence — it is $\{1, 2\}$.

Source: codeforces | Difficulty: MEDIUM
Tags: Sorting

Amortized analysis

Greedy algorithms

Dynamic programming

Data structures


Solutions:
(n, m) = map(int, input().split())
s = input()
t = input()
fast_substring = [0] * m
last_substring = [0] * m
j = 0
for i in range(n):
	if s[i] == t[j]:
		fast_substring[j] = i
		j += 1
	if j == m:
		break
j = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[j]:
		last_substring[j] = i
		j -= 1
	if j < 0:
		break
ans = -1
for i in range(m - 1):
	ans = max(ans, last_substring[i + 1] - fast_substring[i])
print(ans)


def main():
	(n, m) = readIntArr()
	s = input()
	t = input()
	j = 0
	minP = [None for _ in range(m)]
	for i in range(n):
		if s[i] == t[j]:
			minP[j] = i
			j += 1
		if j == m:
			break
	j = m - 1
	maxP = [None for _ in range(m)]
	for i in range(n - 1, -1, -1):
		if s[i] == t[j]:
			maxP[j] = i
			j -= 1
		if j == -1:
			break
	ans = -inf
	for i in range(1, m):
		ans = max(ans, maxP[i] - minP[i - 1])
	print(ans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]
inf = float('inf')
MOD = 10 ** 9 + 7
main()


input()
s = input()
t = input()
n = len(s)
m = len(t)
ls = []
i = 0
for c in t:
	while s[i] != c:
		i += 1
	ls.append(i)
	i += 1
rs = []
i = n - 1
for c in t[::-1]:
	while s[i] != c:
		i -= 1
	rs.append(i)
	i -= 1
rs = rs[::-1]
print(max((rs[i] - ls[i - 1] for i in range(1, m))))


def solve(n, m, s, t):
	idx = [0] * m
	j = 0
	for i in range(n):
		if j < m and t[j] == s[i]:
			idx[j] = i
			j += 1
	res = 0
	j = m - 1
	for i in range(n - 1, -1, -1):
		if j >= 0 and t[j] == s[i]:
			res = max(res, i - idx[j - 1])
			j -= 1
	return res
(n, m) = map(int, input().split())
s = input()
t = input()
print(solve(n, m, s, t))


def solve():
	(n, m) = list(map(int, input().split()))
	s = list(input())
	t = list(input())
	(e, l) = ([0] * m, [0] * m)
	(j, i) = (0, 0)
	while j < m:
		if t[j] == s[i]:
			e[j] = i
			j += 1
		i += 1
	(j, i) = (m - 1, n - 1)
	while j >= 0:
		if t[j] == s[i]:
			l[j] = i
			j -= 1
		i -= 1
	best = 0
	for i in range(m - 1):
		best = max(l[i + 1] - e[i], best)
	return best
print(solve())


from bisect import *
from collections import *
from math import gcd, ceil, sqrt, floor, inf
from heapq import *
from itertools import *
from operator import add, mul, sub, xor, truediv, floordiv
from functools import *
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())

def A(n):
	return [0] * n

def AI(n, x):
	return [x] * n

def G(n):
	return [[] for i in range(n)]

def GP(it):
	return [[ch, len(list(g))] for (ch, g) in groupby(it)]
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
mod = 10 ** 9 + 7
farr = [1]
ifa = []

def fact(x, mod=0):
	if mod:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr) % mod)
	else:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr))
	return farr[x]

def ifact(x, mod):
	global ifa
	fact(x, mod)
	ifa.append(pow(farr[-1], mod - 2, mod))
	for i in range(x, 0, -1):
		ifa.append(ifa[-1] * i % mod)
	ifa.reverse()

def per(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return fact(i) // fact(i - j)
	return farr[i] * ifa[i - j] % mod

def com(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return per(i, j) // fact(j)
	return per(i, j, mod) * ifa[j] % mod

def catalan(n):
	return com(2 * n, n) // (n + 1)

def isprime(n):
	for i in range(2, int(n ** 0.5) + 1):
		if n % i == 0:
			return False
	return True

def floorsum(a, b, c, n):
	if a == 0:
		return b // c * (n + 1)
	if a >= c or b >= c:
		return floorsum(a % c, b % c, c, n) + b // c * (n + 1) + a // c * n * (n + 1) // 2
	m = (a * n + b) // c
	return n * m - floorsum(c, c - b - 1, a, m - 1)

def inverse(a, m):
	a %= m
	if a <= 1:
		return a
	return (1 - inverse(m, a) * m) // a % m

def lowbit(n):
	return n & -n

class BIT:

	def __init__(self, arr):
		self.arr = arr
		self.n = len(arr) - 1

	def update(self, x, v):
		while x <= self.n:
			self.arr[x] += v
			x += x & -x

	def query(self, x):
		ans = 0
		while x:
			ans += self.arr[x]
			x &= x - 1
		return ans

class ST:

	def __init__(self, arr):
		n = len(arr)
		mx = n.bit_length()
		self.st = [[0] * mx for i in range(n)]
		for i in range(n):
			self.st[i][0] = arr[i]
		for j in range(1, mx):
			for i in range(n - (1 << j) + 1):
				self.st[i][j] = max(self.st[i][j - 1], self.st[i + (1 << j - 1)][j - 1])

	def query(self, l, r):
		if l > r:
			return -inf
		s = (r + 1 - l).bit_length() - 1
		return max(self.st[l][s], self.st[r - (1 << s) + 1][s])

class UFS:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.ranks = [0] * n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, u, v):
		(pu, pv) = (self.find(u), self.find(v))
		if pu == pv:
			return False
		if self.ranks[pu] >= self.ranks[pv]:
			self.parent[pv] = pu
			if self.ranks[pv] == self.ranks[pu]:
				self.ranks[pu] += 1
		else:
			self.parent[pu] = pv

def Prime(n):
	c = 0
	prime = []
	flag = [0] * (n + 1)
	for i in range(2, n + 1):
		if not flag[i]:
			prime.append(i)
			c += 1
		for j in range(c):
			if i * prime[j] > n:
				break
			flag[i * prime[j]] = prime[j]
			if i % prime[j] == 0:
				break
	return flag

def dij(s, graph):
	d = {}
	d[s] = 0
	heap = [(0, s)]
	seen = set()
	while heap:
		(dis, u) = heappop(heap)
		if u in seen:
			continue
		seen.add(u)
		for (v, w) in graph[u]:
			if v not in d or d[v] > d[u] + w:
				d[v] = d[u] + w
				heappush(heap, (d[v], v))
	return d

def lcm(a, b):
	return a * b // gcd(a, b)

def lis(nums):
	res = []
	for k in nums:
		i = bisect.bisect_left(res, k)
		if i == len(res):
			res.append(k)
		else:
			res[i] = k
	return len(res)

def RP(nums):
	n = len(nums)
	s = set(nums)
	d = {}
	for (i, k) in enumerate(sorted(s), 1):
		d[k] = i
	bi = BIT([0] * (len(s) + 1))
	ans = 0
	for i in range(n - 1, -1, -1):
		ans += bi.query(d[nums[i]] - 1)
		bi.update(d[nums[i]], 1)
	return ans

class DLN:

	def __init__(self, val):
		self.val = val
		self.pre = None
		self.next = None

def nb(i, j, n, m):
	for (ni, nj) in [[i + 1, j], [i - 1, j], [i, j - 1], [i, j + 1]]:
		if 0 <= ni < n and 0 <= nj < m:
			yield (ni, nj)

def topo(n):
	q = deque()
	res = []
	for i in range(1, n + 1):
		if ind[i] == 0:
			q.append(i)
			res.append(i)
	while q:
		u = q.popleft()
		for v in g[u]:
			ind[v] -= 1
			if ind[v] == 0:
				q.append(v)
				res.append(v)
	return res

@bootstrap
def gdfs(r, p):
	if len(g[r]) == 1 and p != -1:
		yield None
	for ch in g[r]:
		if ch != p:
			yield gdfs(ch, r)
	yield None
t = 1
for i in range(t):
	(n, m) = RL()
	s = input()
	t = input()
	fi = [0] * m
	last = [0] * m
	j = 0
	for i in range(m):
		while t[i] != s[j]:
			j += 1
		fi[i] = j
		j += 1
	j = n - 1
	for i in range(m - 1, -1, -1):
		while t[i] != s[j]:
			j -= 1
		last[i] = j
		j -= 1
	if m == 2:
		ans = last[-1] - fi[0]
	else:
		ans = 0
		for i in range(1, m - 1):
			ans = max(ans, last[i + 1] - fi[i], last[i] - fi[i - 1])
	print(ans)


(n, m) = [int(v) for v in input().split()]
s = input()
t = input()
minSeq = [-1] * m
maxSeq = [-1] * m
j = 0
for i in range(n):
	if s[i] == t[j]:
		minSeq[j] = i
		if j == m - 1:
			break
		j += 1
for i in range(n - 1, -1, -1):
	if s[i] == t[j]:
		maxSeq[j] = i
		if j == 0:
			break
		j -= 1
print(max([maxSeq[i] - minSeq[i - 1] for i in range(1, m)]))


(n, m) = map(int, input().split())
s = list(input())
t = list(input())
start = []
end = []
j = 0
k = n - 1
for i in range(m):
	while s[j] != t[i]:
		j += 1
	start.append(j)
	j += 1
	while s[k] != t[m - 1 - i]:
		k -= 1
	end.append(k)
	k -= 1
end = end[::-1]
ans = 0
for i in range(1, m):
	ans = max(ans, end[i] - start[i - 1])
print(ans)


import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')
(n, m) = map(int, input().split())
a = input()
b = input()
fc = []
t = 0
for i in b:
	while t < n and a[t] != i:
		t += 1
	fc.append(t)
	t += 1
t = n - 1
bc = []
for i in reversed(b):
	while t >= 0 and a[t] != i:
		t -= 1
	bc.append(t)
	t -= 1
ans = 0
bc = bc[::-1]
for i in range(m - 1):
	ans = max(ans, bc[i + 1] - fc[i])
print(ans)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
(s, t) = (input()[:-1], input()[:-1])
(left, right) = ([0] * m, [0] * m)
i = 0
for j in range(m):
	while s[i] != t[j]:
		i += 1
	left[j] = i
	i += 1
i = n - 1
for j in range(m - 1, -1, -1):
	while s[i] != t[j]:
		i -= 1
	right[j] = i
	i -= 1
ans = 0
for i in range(m - 1):
	ans = max(ans, right[i + 1] - left[i])
print(ans)


from pickletools import read_uint1

def GetRightInds(n, m, s, t):
	r_inds = list()
	cur_ind = n - 1
	for q_ind in range(m - 1, 0, -1):
		while s[cur_ind] != t[q_ind]:
			cur_ind -= 1
		r_inds.append(cur_ind)
		cur_ind -= 1
	return r_inds

def Sol(n, m, s, t):
	r_inds = GetRightInds(n, m, s, t)
	r1 = 0
	max_w = 0
	for i in range(m - 1):
		while s[r1] != t[i]:
			r1 += 1
		l2 = r_inds[-1]
		r_inds.pop()
		max_w = max(max_w, l2 - r1)
		r1 += 1
	return max_w
(n, m) = map(int, input().split())
s = input().strip()
t = input().strip()
max_w = Sol(n, m, s, t)
print(max_w)


(n, m) = map(int, input().split())
s = input()
t = input()
p = [0 for i in range(m)]
(i, j) = (0, 0)
while j < m:
	while s[i] != t[j]:
		i += 1
	p[j] = i
	i += 1
	j += 1
sol = 0
i = n - 1
while j > 1:
	j -= 1
	while s[i] != t[j]:
		i -= 1
	sol = max(sol, i - p[j - 1])
	i -= 1
print(sol)


(n, m) = map(int, input().split())
s1 = input()
s2 = input()
a = []
b = []
c = 0
for j in range(n):
	if s1[j] == s2[c]:
		a.append(j)
		c = c + 1
		if c == m:
			break
c = m - 1
for j in range(n - 1, -1, -1):
	if s1[j] == s2[c]:
		b.append(j)
		c = c - 1
		if c == -1:
			break
maxo = 0
for j in range(m - 1):
	if maxo < b[m - 2 - j] - a[j]:
		maxo = b[m - 2 - j] - a[j]
print(maxo)


from collections import deque

def do():
	a2i = lambda x: ord(x) - ord('a')
	(n, m) = map(int, input().split())
	s = input()
	target = input()
	posAlphas = [deque([]) for _ in range(26)]
	loc = [None] * m
	cur = 0
	for i in range(n):
		val = a2i(s[i])
		posAlphas[val].append(i)
	for i in range(m):
		while s[cur] != target[i]:
			cur += 1
		loc[i] = cur
		cur += 1
	res = -1
	for i in range(m - 1):
		res = max(res, loc[i + 1] - loc[i])
	curMax = 10 ** 9
	for i in range(m - 1, 0, -1):
		curLoc = loc[i]
		curChar = a2i(target[i])
		isRewrite = False
		while len(posAlphas[curChar]) > 0:
			canPos = posAlphas[curChar].pop()
			if curMax <= canPos:
				continue
			if canPos <= curLoc:
				break
			isRewrite = True
			loc[i] = canPos
			break
		curMax = loc[i]
		res = max(res, loc[i] - loc[i - 1])
	print(res)
do()


(n, m) = map(int, input().split())
s = input()
t = input()
low = []
pointer = 0
for (index, char) in enumerate(s):
	if char == t[pointer]:
		low.append(index)
		pointer += 1
		if pointer == m:
			break
else:
	raise RuntimeError("Shouldn't reach here")
high = []
pointer = m - 1
for (index, char) in reversed(tuple(enumerate(s))):
	if char == t[pointer]:
		high.append(index)
		pointer -= 1
		if pointer < 0:
			break
else:
	raise ValueError
high.reverse()
print(max((high[i] - low[i - 1] for i in range(1, m))))


(n, m) = map(int, input().split())
s = input()
t = input()
left = [0 for i in range(m)]
right = [0 for i in range(m)]
j = 0
i = 0
while j < m:
	while s[i] != t[j]:
		i += 1
	left[j] = i
	i += 1
	j += 1
j = m - 1
i = n - 1
while j >= 0:
	while s[i] != t[j]:
		i -= 1
	right[j] = i
	i -= 1
	j -= 1
ans = 0
for i in range(1, m):
	ans = max(right[i] - left[i - 1], ans)
print(ans)


import os
import sys
from io import BytesIO, IOBase
from collections import defaultdict

def main():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	l = []
	j = 0
	for i in range(n):
		if s[i] == t[j]:
			l.append(i)
			j += 1
			if j == m:
				break
	r = []
	j = m - 1
	for i in range(n - 1, -1, -1):
		if s[i] == t[j]:
			r.append(i)
			j -= 1
			if j == -1:
				break
	r.reverse()
	ans = 0
	for i in range(m - 1):
		ans = max(ans, r[i + 1] - l[i])
	print(ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


def width(a, b):
	m = len(b)
	idx = 0
	l = [0] * (2 * 10 ** 5 + 5)
	r = [0] * (2 * 10 ** 5 + 5)
	for i in range(len(a)):
		if a[i] == b[idx]:
			l[idx] = i
			idx += 1
			if idx == m:
				break
	idx = m - 1
	for i in range(len(a) - 1, -1, -1):
		if a[i] == b[idx]:
			r[idx] = i
			idx -= 1
			if idx < 0:
				break
	ans = 0
	for i in range(len(b) - 1):
		ans = max(ans, r[i + 1] - l[i])
	return ans
n = input()
a = input()
b = input()
print(width(a, b))


def find():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	ind = 0
	left = []
	right = [0] * m
	for j in range(m):
		while s[ind] != t[j]:
			ind += 1
		left.append(ind)
		ind += 1
	ind = n - 1
	for j in range(m - 1, -1, -1):
		while s[ind] != t[j]:
			ind -= 1
		right[j] = ind
		ind -= 1
	ans = 1
	for j in range(m - 1):
		ans = max(ans, right[j + 1] - left[j])
	print(ans)
find()


def solution():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	rev_s = ''.join(reversed(s))
	rev_t = ''.join(reversed(t))
	last_pos = len(t) * [0]
	start = 0
	for i in range(len(t)):
		idx = rev_s.find(rev_t[i], start)
		last_pos[i] = len(s) - idx - 1
		start = idx + 1
	last_pos.reverse()
	result = 1
	cur_pos = -1
	for i in range(len(t) - 1):
		cur_pos = s.find(t[i], cur_pos + 1)
		result = max(result, last_pos[i + 1] - cur_pos)
	print(result)
solution()


(n, m) = map(int, input().split())
s = input()
t = input()
ptr = 0
first = [0] * m
for i in range(n):
	if t[ptr] == s[i]:
		first[ptr] = i
		ptr += 1
	if ptr == m:
		break
last = [0] * m
ptr = m - 1
for j in range(n - 1, -1, -1):
	if t[ptr] == s[j]:
		last[ptr] = j
		ptr -= 1
	if ptr == -1:
		break
ans = 0
for i in range(1, m):
	ans = max(ans, last[i] - first[i - 1])
print(ans)


def main():
	(n, m) = map(int, input().split())
	s = str(input())
	t = str(input())
	from collections import deque, defaultdict
	import bisect
	X = [[] for i in range(26)]
	for (i, c) in enumerate(s):
		c = ord(c) - ord('a')
		X[c].append(i)
	A = []
	cur = -1
	for (i, c) in enumerate(t):
		c = ord(c) - ord('a')
		j = bisect.bisect_right(X[c], cur)
		A.append(X[c][j])
		cur = X[c][j]
	B = []
	cur = n
	for i in reversed(range(m)):
		c = t[i]
		c = ord(c) - ord('a')
		j = bisect.bisect_left(X[c], cur)
		B.append(X[c][j - 1])
		cur = X[c][j - 1]
	B.reverse()
	ans = 0
	for i in range(m - 1):
		ans = max(ans, A[i + 1] - A[i])
		ans = max(ans, B[i + 1] - A[i])
		ans = max(ans, B[i + 1] - B[i])
	print(ans)
main()


def solve(n, m, s, t):
	l = [-1] * (m + 1)
	for i in range(m):
		for j in range(l[i - 1] + 1, n):
			if s[j] == t[i]:
				l[i] = j
				break
	r = [-1] * (m + 1)
	r[-1] = n
	for i in range(m - 1, -1, -1):
		for j in range(r[i + 1] - 1, -1, -1):
			if s[j] == t[i]:
				r[i] = j
				break
	res = -1
	for i in range(m - 1):
		res = max(res, r[i + 1] - l[i])
	print(res)
(n, m) = map(int, input().split())
s = input()
t = input()
solve(n, m, s, t)


import math

def getint():
	return [int(i) for i in input().split()]

def getstr():
	return [str(i) for i in input().split()]
res1 = [0] * 200009
res2 = [1] * 200009

def solve():
	(n, m) = getint()
	a = input()
	b = input()
	i = 0
	j = 0
	while i < n and j < m:
		if a[i] == b[j]:
			res1[j] = i
			j += 1
		i += 1
	i = n - 1
	j = m - 1
	while i >= 0 and j >= 0:
		if a[i] == b[j]:
			res2[j] = i
			j -= 1
		i -= 1
	ans = 0
	for i in range(1, m):
		ans = max(ans, res2[i] - res1[i - 1])
	print(ans)
solve()


import sys
import io
import math
import collections
import decimal
import itertools
import bisect
import heapq

def input():
	return sys.stdin.readline()[:-1]

def get_dp(N, M, S, T):
	dp = [0] * (N + 1)
	for i in range(N):
		if dp[i] < M and S[i] == T[dp[i]]:
			dp[i + 1] = dp[i] + 1
		else:
			dp[i + 1] = dp[i]
	return dp

def main():
	(N, M) = map(int, input().split())
	S = input()
	T = input()
	dp1 = get_dp(N, M, S, T)
	dp2 = get_dp(N, M, S[::-1], T[::-1])
	P = [0] * M
	k = 1
	for i in range(N):
		if dp1[i + 1] == k:
			P[k - 1] = i
			k += 1
	Q = [0] * M
	k = 1
	for i in range(N):
		if dp2[i + 1] == k:
			Q[k - 1] = N - i - 1
			k += 1
	Q.reverse()
	ans = max((Q[i + 1] - P[i] for i in range(M - 1)))
	print(ans)
main()


import sys
input = sys.stdin.readline
from collections import deque
from math import log10, ceil
I = lambda : int(input())
L = lambda : list(map(int, input().split()))
T = lambda : map(int, input().split())
(n, m) = T()
s = input().strip()
t = input().strip()
(arr1, arr2) = ([0] * m, [0] * m)
c = 0
for i in range(n):
	if c < m and s[i] == t[c]:
		arr1[c] = i
		c += 1
c = m - 1
for i in range(n - 1, -1, -1):
	if c >= 1 and s[i] == t[c]:
		arr2[c] = i
		c -= 1
ans = 0
for i in range(m - 1):
	if arr1[i] < arr2[i + 1]:
		ans = max(ans, arr2[i + 1] - arr1[i])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
last = []
start = []
i = 0
j = 0
while i < n and j < m:
	if s[i] == t[j]:
		start.append(i)
		i += 1
		j += 1
	else:
		i += 1
i = n - 1
j = m - 1
while i >= 0 and j >= 0:
	if s[i] == t[j]:
		last.append(i)
		i -= 1
		j -= 1
	else:
		i -= 1
last = last[::-1]
mx = last[m - 1] - start[m - 2]
for i in range(m - 1, 0, -1):
	mx = max(mx, last[i] - start[i - 1])
print(mx)


import sys
input = sys.stdin.readline
import math
import bisect
from copy import deepcopy as dc
from itertools import accumulate
from collections import Counter, defaultdict, deque

def ceil(U, V):
	return (U + V - 1) // V

def modf1(N, MOD):
	return (N - 1) % MOD + 1
inf = int(1e+18)
mod = int(1000000000.0 + 7)
(n, m) = map(int, input().split())
s = list(input())[:-1]
t = list(input())[:-1]
l = []
r = []
cnt = 0
for i in range(n):
	if cnt == m:
		break
	if t[cnt] == s[i]:
		l.append(i)
		cnt += 1
cnt = m - 1
for i in range(n - 1, -1, -1):
	if cnt == -1:
		break
	if t[cnt] == s[i]:
		r.append(i)
		cnt -= 1
r.reverse()
ans = 1
for i in range(m - 1):
	ans = max(ans, r[i + 1] - l[i])
print(ans)


(_, s, t) = open(0)
r = i = j = -1
a = []
for x in t[:-2]:
	i = s.find(x, i + 1)
	a += (i,)
for x in t[-2:0:-1]:
	j = s.rfind(x, 0, j)
	r = max(r, j - a.pop())
print(r)


import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__
(n, m) = list(map(int, input().split()))
s = input()
t = input()
if n == m or m == 1:
	print(1)
else:
	indexes = [0] * m
	revIndexes = [0] * m
	(front, back) = (0, n - 1)
	for i in range(m):
		while s[front] != t[i]:
			front += 1
		indexes[i] = front
		front += 1
		while s[back] != t[m - 1 - i]:
			back -= 1
		revIndexes[m - 1 - i] = back
		back -= 1
	ans = 1
	for i in range(m - 1):
		ans = max(ans, abs(indexes[i + 1] - revIndexes[i]), abs(indexes[i] - revIndexes[i + 1]))
	print(ans)


import sys
from sys import stdin, stdout
from math import ceil, floor, sqrt, log, log2, log10
from collections import Counter
int_max = float('inf')
int_min = -float('inf')
ANS = []
input = stdin.readline

def solve():
	pass
t = 1
for i in range(t):
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	prefix = [0] * m
	suffix = [0] * m
	i = 0
	st = 0
	while st < m:
		if s[i] == t[st]:
			prefix[st] = i
			st += 1
		i += 1
	st = m - 1
	i = n - 1
	while st >= 0:
		if s[i] == t[st]:
			suffix[st] = i
			st -= 1
		i -= 1
	maxx = -1
	for i in range(m - 1):
		maxx = max(maxx, suffix[i + 1] - prefix[i])
	ANS.append(str(maxx))
print('\n'.join(ANS))


import sys
import math
import bisect
from sys import stdin, stdout
from math import gcd, floor, sqrt, log2, ceil
from collections import defaultdict as dd
from bisect import bisect_left as bl, bisect_right as br
from bisect import insort
from collections import Counter
from collections import deque
from heapq import heappush, heappop, heapify
from itertools import permutations, combinations
from itertools import accumulate as ac
mod = int(1000000000.0) + 7
ip = lambda : int(stdin.readline())
inp = lambda : map(int, stdin.readline().split())
ips = lambda : stdin.readline().rstrip()
out = lambda x: stdout.write(str(x) + '\n')
t = 1
for _ in range(t):
	(n, m) = inp()
	a = ips()
	b = ips()
	pref = []
	c = 0
	i = 0
	while c < m:
		if a[i] == b[c]:
			pref.append(i)
			c += 1
		i += 1
	suff = []
	c = m - 1
	i = n - 1
	while c >= 0:
		if a[i] == b[c]:
			suff.append(i)
			c -= 1
		i -= 1
	ans = []
	suff = suff[::-1]
	for i in range(1, m):
		ans.append(suff[i] - pref[i - 1])
	ans = max(ans)
	print(ans)


def find_good_chain(s, t):
	x = 0
	y = 0
	ind = []
	while x < len(t):
		while s[y] != t[x]:
			y = y + 1
		ind.append(y)
		x = x + 1
		y = y + 1
	return ind

def find_reversed_chain(s, t):
	x = len(t) - 1
	y = len(s) - 1
	ind = []
	while x >= 0:
		while s[y] != t[x]:
			y = y - 1
		ind.append(y)
		x = x - 1
		y = y - 1
	return list(reversed(ind))

def get_max(ind1, ind2):
	curr_max = 0
	for i in range(1, len(ind1)):
		if ind2[i] - ind1[i - 1] > curr_max:
			curr_max = ind2[i] - ind1[i - 1]
	return curr_max
from sys import stdin as f
(m, n) = [int(i) for i in f.readline().strip().split()]
s = f.readline().strip()
t = f.readline().strip()
ind1 = find_good_chain(s, t)
ind2 = find_reversed_chain(s, t)
curr_max = get_max(ind1, ind2)
print(curr_max)


(n, m) = map(int, input().split())
s = input()
t = input()
l = [0] * m
r = [0] * m
i = 0
j = 0
while j < m:
	if s[i] == t[j]:
		l[j] = i
		j += 1
	i += 1
i = n - 1
j = m - 1
while j > 0:
	if s[i] == t[j]:
		r[j] = i
		j -= 1
	i -= 1
print(max((r[i + 1] - l[i] for i in range(m - 1))))


import sys
input = sys.stdin.readline

def solve():
	(n, m) = map(int, input().split())
	s = input().strip()
	t = input().strip()
	leftmost = [0] * m
	rightmost = [0] * m
	curr = 0
	for i in range(n):
		if s[i] == t[curr]:
			leftmost[curr] = i
			curr += 1
			if curr == m:
				break
	curr = m - 1
	for i in range(n - 1, -1, -1):
		if s[i] == t[curr]:
			rightmost[curr] = i
			curr -= 1
			if curr < 0:
				break
	ans = 0
	for j in range(m - 1):
		ans = max(ans, rightmost[j + 1] - leftmost[j])
	return ans
print(solve())


from collections import defaultdict
import bisect
for _ in range(1):
	(n, m) = map(int, input().split())
	s = input().strip()
	t = input().strip()
	f = 0
	left = []
	for i in range(n):
		if s[i] == t[f]:
			left.append(i)
			f += 1
		if f == m:
			break
	f = m - 1
	right = []
	for i in range(n - 1, -1, -1):
		if s[i] == t[f]:
			right.append(i)
			f -= 1
		if f == -1:
			break
	right.reverse()
	ans = 0
	for i in range(1, m):
		ans = max(ans, right[i] - left[i - 1])
	print(ans)


(n, m) = map(int, input().split())
(a, b, q, w, e) = (input(), input(), [], [], 0)
for i in range(n):
	if b[e] == a[i]:
		q += [i]
		e += 1
	if e == m:
		break
e -= 1
for i in range(n - 1, -1, -1):
	if b[e] == a[i]:
		w += [i]
		e -= 1
	if e == -1:
		break
w = w[::-1]
print(max((w[i + 1] - q[i] for i in range(m - 1))))


(n, m) = list(map(int, input().split()))
a = list(input())
b = list(input())
poses = []
it = 0
for i in range(m):
	while a[it] != b[i]:
		it += 1
	poses.append(it)
	it += 1
last = n - 1
ma = 0
for i in range(1, ma):
	m = max(poses[i] - poses[i - 1], ma)
for i in range(m - 1, 0, -1):
	while a[last] != b[i]:
		last -= 1
	ma = max(last - poses[i - 1], ma)
	last -= 1
print(ma)


(n, m) = map(int, input().split())
s = input()
t = input()
earliestMatchingIndices = []
j = 0
for c in t:
	while s[j] != c:
		j += 1
	earliestMatchingIndices.append(j)
	j += 1
latestMatchingIndices = [0] * m
j = n - 1
for i in range(m - 1, -1, -1):
	while s[j] != t[i]:
		j -= 1
	latestMatchingIndices[i] = j
	j -= 1
maxWidth = 0
for i in range(0, m - 1):
	maxWidth = max(latestMatchingIndices[i + 1] - earliestMatchingIndices[i], maxWidth)
print(maxWidth)


(n, m) = map(int, input().split())
s = input()
t = input()

def findFirstOption(n, m, s, t):
	firstOccurrence = [0 for _ in range(m)]
	cur = 0
	for i in range(n):
		if cur == m:
			break
		chS = ord(s[i]) - ord('a')
		chT = ord(t[cur]) - ord('a')
		if chT == chS:
			firstOccurrence[cur] = i
			cur += 1
	return firstOccurrence
a = findFirstOption(n, m, s, t)
b = [n - 1 - x for x in findFirstOption(n, m, s[::-1], t[::-1])[::-1]]
print(max([b[i + 1] - a[i] for i in range(m - 1)]))


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
(s, t) = (input().strip(), input().strip())
(forward_index, reverse_index, i, j, ans) = ([], [], 0, 0, 0)
while i < n and j < m:
	if s[i] == t[j]:
		forward_index.append(i)
		(i, j) = (i + 1, j + 1)
	else:
		i += 1
(i, j) = (n - 1, m - 1)
while i > -1 and j > -1:
	if s[i] == t[j]:
		reverse_index.append(i)
		(i, j) = (i - 1, j - 1)
	else:
		i -= 1
reverse_index = reverse_index[0:len(reverse_index) - 1][::-1]
for i in range(len(forward_index) - 1):
	ans = max(ans, reverse_index[i] - forward_index[i])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
mini = []
maxi = []
i = 0
j = 0
while j < m:
	if s[i] == t[j]:
		mini.append(i)
		i += 1
		j += 1
	else:
		i += 1
j = m - 1
i = n - 1
while j >= 0:
	if s[i] == t[j]:
		maxi.append(i)
		i -= 1
		j -= 1
	else:
		i -= 1
maxi.reverse()
ans = 0
for i in range(1, m):
	ans = max(ans, maxi[i] - mini[i - 1])
print(ans)


import math
import sys
import collections
import bisect
import time

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def get_list():
	return list(map(int, sys.stdin.readline().strip().split()))

def get_string():
	return sys.stdin.readline().strip()
for tc in range(1):
	(n, m) = get_ints()
	s = list(get_string())
	t = list(get_string())
	mini = []
	maxi = []
	i = 0
	j = 0
	while j < m:
		if s[i] == t[j]:
			mini.append(i)
			i += 1
			j += 1
		else:
			i += 1
	j = m - 1
	i = n - 1
	while j >= 0:
		if s[i] == t[j]:
			maxi.append(i)
			i -= 1
			j -= 1
		else:
			i -= 1
	maxi.reverse()
	sol = 0
	for i in range(1, len(maxi)):
		sol = max(sol, maxi[i] - mini[i - 1])
	print(sol)


(n, m) = [int(i) for i in input().split()]
(s, t) = [input() for i in range(2)]
qw = {}
ind = n
for i in range(m - 1, -1, -1):
	for j in range(ind - 1, -1, -1):
		if s[j] == t[i]:
			qw[i] = j
			ind = j
			break
raz = 0
ind = -1
for i in range(1, m):
	for j in range(ind + 1, n):
		if s[j] == t[i - 1]:
			ind = j
			break
	k = qw[i] - ind
	raz = max(raz, k)
print(raz)


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

def mapIn():
	return map(int, input().split())
(n, m) = mapIn()
s = input()
t = input()
minrr = [0] * m
maxrr = [0] * m
i = 0
for j in range(m):
	while s[i] != t[j] and i < n:
		i += 1
	minrr[j] = i
	i += 1
i = n - 1
for j in range(m - 1, -1, -1):
	while s[i] != t[j] and i > 0:
		i -= 1
	maxrr[j] = i
	i -= 1
x = 0
for i in range(1, m):
	y = maxrr[i] - minrr[i - 1]
	if y > x:
		x = y
print(x)


import sys

def solve(s, t, n, m):
	P_min = []
	P_max = []
	i = 0
	j = 0
	while i < n and j < m:
		if s[i] == t[j]:
			P_min.append(i)
			j += 1
		i += 1
	i = n - 1
	j = m - 1
	while i >= 0 and j >= 0:
		if s[i] == t[j]:
			P_max.append(i)
			j -= 1
		i -= 1
	P_max = P_max[::-1]
	max_val = 1
	for i in range(len(P_max) - 1):
		max_val = max(max_val, P_max[i + 1] - P_min[i])
	return max_val
if 1 == 2:
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
else:
	input = sys.stdin.readline
(n, m) = list(map(int, input().split()))
s = input()
t = input()
print(solve(s, t, n, m))


import math
import collections
import sys
sys.setrecursionlimit(100000000)

def read_list() -> list:
	return [int(i) for i in input().strip().split()]

def read_num() -> int:
	return int(input().strip())
(n, m) = read_list()
s = input()
t = input()
(st, ed) = ([], [])
p = 0
for i in range(n):
	if s[i] == t[p]:
		st.append(i)
		p += 1
	if p == m:
		break
p = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[p]:
		ed.append(i)
		p -= 1
	if p < 0:
		break
ed.reverse()
ans = 0
for i in range(1, m):
	ans = max(ans, ed[i] - st[i - 1])
print(ans)


def solution():
	(n, m) = map(int, input().split())
	(s, t) = (input(), input())
	ans = 0
	left_right = [[-1 for i in range(2)] for j in range(m)]
	index = 0
	for i in range(m):
		while s[index] != t[i]:
			index += 1
		left_right[i][0] = index
		index += 1
	index = n - 1
	for j in range(m - 1, -1, -1):
		while s[index] != t[j]:
			index -= 1
		left_right[j][1] = index
		index -= 1
	for a in range(m - 1):
		ans = max(ans, left_right[a + 1][1] - left_right[a][0])
	print(ans)
solution()


(n, m) = map(int, input().split())
s = input()
t = input()
pre = [0 for i in range(m)]
suf = [0 for i in range(m)]
j = 0
for i in range(n):
	if j < m and s[i] == t[j]:
		pre[j] = i
		j += 1
j = m - 1
for i in range(n - 1, -1, -1):
	if j >= 0 and s[i] == t[j]:
		suf[j] = i
		j -= 1
ans = 0
for i in range(m - 1):
	ans = max(ans, suf[i + 1] - pre[i])
print(ans)


(n, m) = map(int, input().strip().split())
s = input()
p = input()
x = []
y = []
j = 0
for i in range(n):
	if s[i] == p[j]:
		x.append(i)
		j += 1
	if j == m:
		break
j = m - 1
i = n - 1
while i >= 0 and j >= 0:
	if s[i] == p[j]:
		y.append(i)
		j -= 1
	i -= 1
y.reverse()
ans = 0
for i in range(m - 1):
	ans = max(ans, y[i + 1] - x[i])
print(ans)


import math
import random
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
mod = 10 ** 9 + 7
mod1 = 998244353
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class SegmentTree:

	def __init__(self, data, default=2 ** 51, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)
for ik in range(1):
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	ans = 1
	cou = defaultdict(int)
	ind = defaultdict(list)
	ind1 = defaultdict(list)
	end = [0] * n
	st = [0] * n
	last = 2 * n
	for i in range(n):
		ind[s[i]].append(i)
		ind1[s[i]].append(i)
	for i in range(m - 1, -1, -1):
		while ind[t[i]][-1] >= last:
			ind[t[i]].pop()
		end[i] = ind[t[i]][-1]
		last = end[i]
	last = -1
	for i in range(m):
		while ind1[t[i]][cou[t[i]]] <= last:
			cou[t[i]] += 1
		st[i] = ind1[t[i]][cou[t[i]]]
		last = st[i]
	for i in range(m - 1):
		te = end[i + 1] - st[i]
		ans = max(ans, te)
	print(ans)


import math
import sys

def inpu():
	return sys.stdin.readline().strip()
lets = 'abcdefghijklmnopqrstuvwxyz'
key = {lets[i]: i for i in range(26)}
(n, m) = map(int, input().split())
s = input()
t = input()
d = False
mins = [-1] * m
j = 0
for i in range(n):
	if s[i] == t[j]:
		mins[j] = i
		j += 1
	if j >= m:
		break
maxs = [-1] * m
j = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[j]:
		maxs[j] = i
		j -= 1
	if j < 0:
		break
ans = 0
for i in range(1, m):
	ans = max(maxs[i] - mins[i - 1], ans)
print(ans)


__version__ = '3.0'
__date__ = '2021-03-08'
import sys

def solve(n, m, s, t):
	left_pos = [-1] * m
	right_pos = [-1] * m
	curr = 0
	for pos in range(n):
		if curr == m:
			break
		if s[pos] == t[curr]:
			left_pos[curr] = pos
			curr += 1
	curr = m - 1
	for pos in range(n - 1, -1, -1):
		if curr == -1:
			break
		if s[pos] == t[curr]:
			right_pos[curr] = pos
			curr -= 1
	answer = 1
	for i in range(m - 1):
		answer = max(answer, right_pos[i + 1] - left_pos[i])
	return answer

def main(argv=None):
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	print(solve(n, m, s, t))
	return 0
STATUS = main()
sys.exit(STATUS)


def sol(s, t):
	n = len(s)
	m = len(t)
	first = []
	j1 = 0
	for i in range(n):
		if s[i] == t[j1]:
			j1 += 1
			first.append(i)
		if j1 == m:
			break
	last = []
	j1 = m - 1
	for i in range(n - 1, -1, -1):
		if s[i] == t[j1]:
			j1 -= 1
			last.append(i)
		if j1 == -1:
			break
	answer = 0
	for i in range(m - 1):
		a1 = first[i]
		a2 = last[m - (i + 1) - 1]
		answer = max(answer, a2 - a1)
	return answer
(n, m) = map(int, input().split())
s = input()
t = input()
print(sol(s, t))


def fill(s, t, f):
	j = 0
	i = 0
	l = [0] * len(t)
	while i < m:
		while t[i] != s[j]:
			j += 1
		if not f:
			l[i] = n - 1 - j
		else:
			l[i] = j
		i += 1
		j += 1
	return l
(n, m) = list(map(int, input().split()))
s = input()
t = input()
forward = fill(s, t, True)
backward = fill(s[::-1], t[::-1], False)[::-1]
m = 0
for i in range(1, len(t)):
	m = max(m, backward[i] - forward[i - 1])
print(m)


(n, m) = map(int, input().split(' '))
s = [w for w in input()]
t = [w for w in input()]
left = []
j = 0
for i in range(n):
	if s[i] == t[j]:
		left.append(i)
		j = j + 1
	if j >= m:
		break
right = []
i = n - 1
j = m - 1
while i >= 0:
	if s[i] == t[j]:
		right.append(i)
		j = j - 1
	if j < 0:
		break
	i = i - 1
right.reverse()
if m > 2:
	ans = 0
	prev = left[0]
	for i in range(1, m - 1):
		ans = max(ans, right[i] - prev)
		prev = left[i]
	ans = max(ans, right[-1] - left[-2])
else:
	ans = right[-1] - left[0]
print(ans)


for u in range(1):
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	left = []
	right = []
	p = 0
	for i in range(n):
		if s[i] == t[p]:
			left.append(i)
			p += 1
		if p == m:
			break
	p = m - 1
	for i in range(n - 1, -1, -1):
		if s[i] == t[p]:
			right.append(i)
			p -= 1
		if p == -1:
			break
	right = right[::-1]
	ans = -1
	for i in range(1, m):
		ans = max(ans, right[i] - left[i - 1])
	print(ans)


from sys import stdin, stdout
input = stdin.readline
from collections import Counter
(n, m) = map(int, input().split(' '))
s = input()
t = input()
lefts = []
rights = []
r = 0
for i in range(n):
	if s[i] == t[r]:
		r += 1
		lefts.append(i)
r = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[r]:
		r -= 1
		rights.append(i)
rights = rights[::-1]
ans = [rights[i] - lefts[i - 1] for i in range(1, m)]
print(max(ans))


from __future__ import division, print_function
import os, sys
from io import BytesIO, IOBase
if sys.version_info[0] < 3:
	from __builtin__ import xrange as range
	from future_builtins import ascii, filter, hex, map, oct, zip

def ii():
	return int(input())

def fi():
	return float(input())

def si():
	return input()

def msi():
	return map(str, input().split())

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

def li():
	return list(mi())

def lsi():
	return list(msi())

def read():
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

def gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x

def lcm(x, y):
	return x * y // gcd(x, y)
mod = 1000000007

def modInverse(b, m):
	g = gcd(b, m)
	if g != 1:
		return -1
	else:
		return pow(b, m - 2, m)

def ceil(x, y):
	if x % y == 0:
		return x // y
	else:
		return x // y + 1

def modu(a, b, m):
	a = a % m
	inv = modInverse(b, m)
	if inv == -1:
		return -999999999
	else:
		return inv * a % m
from math import log, factorial, cos, tan, sin, radians, floor, sqrt, log2
import bisect
import random
import string
from decimal import *
getcontext().prec = 50
abc = 'abcdefghijklmnopqrstuvwxyz'
pi = 3.141592653589793

def gcd1(a):
	if len(a) == 1:
		return a[0]
	ans = a[0]
	for i in range(1, len(a)):
		ans = gcd(ans, a[i])
	return ans

def mykey(x):
	return (x[0], -x[1])

def main():
	for _ in range(1):
		(n, m) = mi()
		s = si()
		t = si()
		a = []
		b = []
		j = m - 1
		for i in range(n - 1, -1, -1):
			if j == -1:
				break
			if s[i] == t[j]:
				a.append(i)
				j -= 1
		a = a[::-1]
		j = 0
		for i in range(n):
			if j == m:
				break
			if s[i] == t[j]:
				b.append(i)
				j += 1
		ans = -1
		for i in range(m - 1):
			ans = max(ans, a[i + 1] - b[i], b[i + 1] - a[i])
		print(ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


(n, m) = map(int, input().split())
s = input()
t = input()
i = 0
ls = []
for c in t:
	while s[i] != c:
		i = i + 1
	ls.append(i)
	i = i + 1
rs = []
i = n - 1
for c in t[::-1]:
	while s[i] != c:
		i = i - 1
	rs.append(i)
	i = i - 1
maxi = 0
rs = rs[::-1]
for i in range(0, m):
	maxi = max(maxi, rs[i] - ls[i - 1])
print(maxi)


from os import path
import sys, time
from math import ceil, floor, gcd, log, log2, factorial, sqrt
from collections import defaultdict, Counter, OrderedDict, deque
from itertools import combinations, permutations
from functools import reduce
from operator import mul
maxx = float('inf')
I = lambda : int(sys.stdin.buffer.readline())
tup = lambda : map(int, sys.stdin.buffer.readline().split())
lint = lambda : [int(x) for x in sys.stdin.buffer.readline().split()]
S = lambda : sys.stdin.readline().strip('\n')
grid = lambda r: [lint() for i in range(r)]
stpr = lambda x: sys.stdout.write(f'{x}' + '\n')
star = lambda x: print(' '.join(map(str, x)))
localsys = 0
start_time = time.time()
if path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

def ceill(n, x):
	return (n + x - 1) // x
(n, m) = map(int, S().split())
(s, t) = (S(), S())
(l, r, i, j) = ([], [], 0, n - 1)
for x in t:
	while i < n and s[i] != x:
		i += 1
	l.append(i)
	i += 1
for x in t[::-1]:
	while j > -1 and s[j] != x:
		j -= 1
	r.append(j)
	j -= 1
r.reverse()
print(max([r[i] - l[i - 1] for i in range(1, m)]))
if localsys:
	print('\n\nTime Elased :', time.time() - start_time, 'seconds')


(n, m) = map(int, input().split())
s = input()
t = input()
l_idx = []
r_idx = []
(l, r) = (0, m - 1)
for i in range(n):
	if s[i] == t[l]:
		l_idx.append(i)
		l += 1
	if l == m:
		break
for i in range(n - 1, -1, -1):
	if s[i] == t[r]:
		r_idx.append(i)
		r -= 1
	if r < 0:
		break
r_idx.reverse()
ans = 0
for i in range(m - 1):
	ans = max(ans, r_idx[i + 1] - l_idx[i])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
mn = [0] * m
mx = [0] * m
p = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[p]:
		mx[p] = i
		p -= 1
		if p == -1:
			break
p = 0
for i in range(n):
	if s[i] == t[p]:
		mn[p] = i
		p += 1
		if p == m:
			break
out = 0
for i in range(1, m):
	out = max(out, mx[i] - mn[i - 1])
print(out)


def answer():
	(l, r) = ([0] * (n + 1), [0] * (n + 1))
	ind = 0
	for i in range(n):
		if s1[i] == s2[ind]:
			l[ind] = i
			ind += 1
			if ind == m:
				break
	ind = m - 1
	for i in range(n - 1, -1, -1):
		if s1[i] == s2[ind]:
			r[ind] = i
			ind -= 1
			if ind < 0:
				break
	ans = 0
	for i in range(n):
		ans = max(ans, r[i + 1] - l[i])
	return ans
(n, m) = map(int, input().split())
s1 = input()
s2 = input()
print(answer())


import sys

def solve(s, t):
	left_indexs = []
	right_indexs = []
	counter = 0
	ans = 0
	for (i, c) in enumerate(s):
		if counter + 1 == len(t):
			break
		if t[counter] == c:
			left_indexs.append(i)
			counter += 1
	counter = len(t) - 1
	for (i, c) in enumerate(s[::-1]):
		if counter == 0:
			break
		if t[counter] == c:
			right_indexs.append(len(s) - i - 1)
			counter -= 1
	for i in range(len(left_indexs)):
		ans = max(ans, right_indexs[i] - left_indexs[len(left_indexs) - i - 1])
	return ans
n = sys.stdin.readline().strip()
s = sys.stdin.readline().strip()
t = sys.stdin.readline().strip()
print(solve(s, t))


from __future__ import division, print_function
from fractions import Fraction
import sys
import os
from io import BytesIO, IOBase
from functools import cmp_to_key
from heapq import *
from math import gcd, factorial, floor, ceil, sqrt, log2
from copy import deepcopy
from collections import deque
from bisect import bisect_left as bl
from bisect import bisect_right as br
from bisect import bisect
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
from types import GeneratorType

def iterative(f, stack=[]):

	def wrapped_func(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		to = f(*args, **kwargs)
		while True:
			if type(to) is GeneratorType:
				stack.append(to)
				to = next(to)
				continue
			stack.pop()
			if not stack:
				break
			to = stack[-1].send(to)
		return to
	return wrapped_func

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def out(var):
	sys.stdout.write(str(var))

def lis():
	return list(map(int, inp().split()))

def stringlis():
	return list(map(str, inp().split()))

def sep():
	return map(int, inp().split())

def strsep():
	return map(str, inp().split())

def testcase(t):
	for pp in range(t):
		solve(pp)

def google(p):
	print('Case #' + str(p) + ': ', end='')

def lcm(a, b):
	return a * b // gcd(a, b)

def power(x, y, p):
	y %= p - 1
	res = 1
	x = x % p
	if x == 0:
		return 0
	while y > 0:
		if y & 1 == 1:
			res = res * x % p
		y = y >> 1
		x = x * x % p
	return res

def ncr(n, r):
	return factorial(n) // (factorial(r) * factorial(max(n - r, 1)))

def isPrime(n):
	if n <= 1:
		return False
	if n <= 3:
		return True
	if n % 2 == 0 or n % 3 == 0:
		return False
	i = 5
	while i * i <= n:
		if n % i == 0 or n % (i + 2) == 0:
			return False
		i = i + 6
	return True
inf = pow(10, 20)
mod = 10 ** 9 + 7

class RangeQuery:

	def __init__(self, data, func=max):
		self.func = func
		self._data = _data = [list(data)]
		(i, n) = (1, len(_data[0]))
		while 2 * i <= n:
			prev = _data[-1]
			_data.append([func(prev[j], prev[j + i]) for j in range(n - 2 * i + 1)])
			i <<= 1

	def query(self, start, stop):
		depth = (stop - start).bit_length() - 1
		return self.func(self._data[depth][start], self._data[depth][stop - (1 << depth)])

	def __getitem__(self, idx):
		return self._data[0][idx]

def do(s, t):
	n = len(s)
	m = len(t)
	j = 0
	have = []
	ans = -inf
	for i in range(n):
		if s[i] == t[j]:
			if len(have) > 0:
				ans = max(ans, i - have[-1])
			have.append(i)
			j += 1
		if j == m:
			ind = i
			for j in range(i, n):
				if s[j] == t[-1]:
					ind = j
			ans = max(ans, ind - have[-2])
			j = m - 2
			cnt = 2
			for k in range(ind - 1, -1, -1):
				if j == 0:
					break
				if s[k] == t[j]:
					ans = max(ans, k - have[-(cnt + 1)])
					cnt += 1
					j -= 1
			break
	return ans

def solve(case):
	(n, m) = sep()
	s = list(inp())
	t = list(inp())
	ind = {}
	for i in range(n):
		if s[i] not in ind:
			ind[s[i]] = [i]
		else:
			ind[s[i]].append(i)
	tot = -inf
	tot = max(tot, do(s, t))
	print(tot)
testcase(1)


import sys
import math
from bisect import bisect_left
from collections import defaultdict
import decimal as decimal

def get_lcp(s, suffix_array):
	s = s + '$'
	n = len(s)
	lcp = [0] * n
	pos = [0] * n
	for i in range(n - 1):
		pos[suffix_array[i]] = i
	k = 0
	for i in range(n - 1):
		if k > 0:
			k -= 1
		if pos[i] == n - 1:
			lcp[n - 1] = -1
			k = 0
			continue
		else:
			j = suffix_array[pos[i] + 1]
			while max([i + k, j + k]) < n and s[i + k] == s[j + k]:
				k += 1
			lcp[pos[i]] = k
	return lcp

def get_suffix_array(word):
	suffix_array = [('', len(word))]
	for position in range(len(word)):
		sliced = word[len(word) - position - 1:]
		suffix_array.append((sliced, len(word) - position - 1))
	suffix_array.sort(key=lambda x: x[0])
	return [item[1] for item in suffix_array]

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def bin_search(collection, element):
	i = bisect_left(collection, element)
	if i != len(collection) and collection[i] == element:
		return i
	else:
		return -1

def main():
	(n, m) = map(int, input().split())
	s = str(input())
	t = str(input())
	right = [0] * m
	left = [0] * m
	curr = m - 1
	for i in range(n - 1, -1, -1):
		if curr > 0 and s[i] == t[curr]:
			right[curr] = i
			curr -= 1
	curr = 0
	for i in range(n):
		if curr < m and s[i] == t[curr]:
			left[curr] = i
			curr += 1
	ans = 0
	for i in range(m - 1):
		ans = max(right[i + 1] - left[i], ans)
	print(ans)
main()


(n, m) = map(int, input().split(' '))
s = input()
t = input()
minm = [0] * m
i = 0
for j in range(n):
	if i == m:
		break
	if s[j] == t[i]:
		minm[i] = j
		i += 1
maxm = [0] * m
i = m - 1
for j in range(n - 1, -1, -1):
	if i == -1:
		break
	if s[j] == t[i]:
		maxm[i] = j
		i -= 1
mx = -1
for i in range(1, m):
	if maxm[i] - minm[i - 1] > mx:
		mx = maxm[i] - minm[i - 1]
print(mx)


def solve(n, m):
	l = []
	r = []
	(i1, i2) = (0, 0)
	while i1 < n and i2 < m:
		if s[i1] == t[i2]:
			l.append(i1)
			i2 += 1
		i1 += 1
	(i1, i2) = (n - 1, m - 1)
	while i1 > -1 and i2 > -1:
		if s[i1] == t[i2]:
			r.append(i1)
			i2 -= 1
		i1 -= 1
	maxx = 0
	r = r[::-1]
	for i in range(m - 1):
		maxx = max(maxx, r[i + 1] - l[i])
	print(maxx)
(n, m) = map(int, input().split())
s = input()
t = input()
solve(n, m)


import math
from bisect import bisect_right
from bisect import bisect_left
from collections import defaultdict
(n, m) = map(int, input().split())
s = input()
k = input()
a = []
b = []
for j in s:
	a.append(j)
for j in k:
	b.append(j)
ind = defaultdict(lambda : [])
for j in range(n):
	ind[a[j]].append(j)
val = [0] * m
last = -1
j = 0
while j < m:
	val[j] = ind[b[j]][bisect_right(ind[b[j]], last)]
	last = val[j]
	j += 1
val1 = [0] * m
last = float('inf')
j = m - 1
while j >= 0:
	val1[j] = ind[b[j]][bisect_left(ind[b[j]], last) - 1]
	last = val1[j]
	j += -1
j = m - 1
ans = 1
while j >= 1:
	curr = b[j]
	ans = max(ans, val1[j] - val[j - 1])
	ind[curr].pop()
	j += -1
print(ans)


(n, m) = [int(k) for k in input().split()]
s = input()
t = input()
c = -1
res = []
for j in range(n):
	if s[-j - 1] == t[c]:
		res.append(n - j - 1)
		c -= 1
		if c < -m:
			break
mx = 0
c = 0
res = res[::-1]
for j in range(n):
	if s[j] == t[c]:
		mx = max(res[c + 1] - j, mx)
		c += 1
		if c == m - 1:
			break
print(mx)


def divisors(M):
	d = []
	i = 1
	while M >= i ** 2:
		if M % i == 0:
			d.append(i)
			if i ** 2 != M:
				d.append(M // i)
		i = i + 1
	return d

def popcount(x):
	x = x - (x >> 1 & 1431655765)
	x = (x & 858993459) + (x >> 2 & 858993459)
	x = x + (x >> 4) & 252645135
	x = x + (x >> 8)
	x = x + (x >> 16)
	return x & 127

def eratosthenes(n):
	res = [0 for i in range(n + 1)]
	prime = set([])
	for i in range(2, n + 1):
		if not res[i]:
			prime.add(i)
			for j in range(1, n // i + 1):
				res[i * j] = 1
	return prime

def factorization(n):
	res = []
	for p in prime:
		if n % p == 0:
			while n % p == 0:
				n //= p
			res.append(p)
	if n != 1:
		res.append(n)
	return res

def euler_phi(n):
	res = n
	for x in range(2, n + 1):
		if x ** 2 > n:
			break
		if n % x == 0:
			res = res // x * (x - 1)
			while n % x == 0:
				n //= x
	if n != 1:
		res = res // n * (n - 1)
	return res

def ind(b, n):
	res = 0
	while n % b == 0:
		res += 1
		n //= b
	return res

def isPrimeMR(n):
	d = n - 1
	d = d // (d & -d)
	L = [2, 3, 5, 7, 11, 13, 17]
	for a in L:
		t = d
		y = pow(a, t, n)
		if y == 1:
			continue
		while y != n - 1:
			y = y * y % n
			if y == 1 or t == n - 1:
				return 0
			t <<= 1
	return 1

def findFactorRho(n):
	from math import gcd
	m = 1 << n.bit_length() // 8
	for c in range(1, 99):
		f = lambda x: (x * x + c) % n
		(y, r, q, g) = (2, 1, 1, 1)
		while g == 1:
			x = y
			for i in range(r):
				y = f(y)
			k = 0
			while k < r and g == 1:
				ys = y
				for i in range(min(m, r - k)):
					y = f(y)
					q = q * abs(x - y) % n
				g = gcd(q, n)
				k += m
			r <<= 1
		if g == n:
			g = 1
			while g == 1:
				ys = f(ys)
				g = gcd(abs(x - ys), n)
		if g < n:
			if isPrimeMR(g):
				return g
			elif isPrimeMR(n // g):
				return n // g
			return findFactorRho(g)

def primeFactor(n):
	i = 2
	ret = {}
	rhoFlg = 0
	while i * i <= n:
		k = 0
		while n % i == 0:
			n //= i
			k += 1
		if k:
			ret[i] = k
		i += 1 + i % 2
		if i == 101 and n >= 2 ** 20:
			while n > 1:
				if isPrimeMR(n):
					(ret[n], n) = (1, 1)
				else:
					rhoFlg = 1
					j = findFactorRho(n)
					k = 0
					while n % j == 0:
						n //= j
						k += 1
					ret[j] = k
	if n > 1:
		ret[n] = 1
	if rhoFlg:
		ret = {x: ret[x] for x in sorted(ret)}
	return ret

def divisors(n):
	res = [1]
	prime = primeFactor(n)
	for p in prime:
		newres = []
		for d in res:
			for j in range(prime[p] + 1):
				newres.append(d * p ** j)
		res = newres
	res.sort()
	return res

def floor_sum(n: int, m: int, a: int, b: int) -> int:
	ans = 0
	if a >= m:
		ans += (n - 1) * n * (a // m) // 2
		a %= m
	if b >= m:
		ans += n * (b // m)
		b %= m
	y_max = (a * n + b) // m
	x_max = y_max * m - b
	if y_max == 0:
		return ans
	ans += (n - (x_max + a - 1) // a) * y_max
	ans += floor_sum(y_max, a, m, (a - x_max % a) % a)
	return ans

def xorfactorial(num):
	if num == 0:
		return 0
	elif num == 1:
		return 1
	elif num == 2:
		return 3
	elif num == 3:
		return 0
	else:
		x = baseorder(num)
		return 2 ** x * ((num - 2 ** x + 1) % 2) + function(num - 2 ** x)

def xorconv(n, X, Y):
	if n == 0:
		res = [X[0] * Y[0] % mod]
		return res
	x = [X[i] + X[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	y = [Y[i] + Y[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	z = [X[i] - X[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	w = [Y[i] - Y[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	res1 = xorconv(n - 1, x, y)
	res2 = xorconv(n - 1, z, w)
	former = [(res1[i] + res2[i]) * inv for i in range(2 ** (n - 1))]
	latter = [(res1[i] - res2[i]) * inv for i in range(2 ** (n - 1))]
	former = list(map(lambda x: x % mod, former))
	latter = list(map(lambda x: x % mod, latter))
	return former + latter

def merge_sort(A, B):
	(pos_A, pos_B) = (0, 0)
	(n, m) = (len(A), len(B))
	res = []
	while pos_A < n and pos_B < m:
		(a, b) = (A[pos_A], B[pos_B])
		if a < b:
			res.append(a)
			pos_A += 1
		else:
			res.append(b)
			pos_B += 1
	res += A[pos_A:]
	res += B[pos_B:]
	return res

class UnionFindVerSize:

	def __init__(self, N):
		self._parent = [n for n in range(0, N)]
		self._size = [1] * N
		self.group = N

	def find_root(self, x):
		if self._parent[x] == x:
			return x
		self._parent[x] = self.find_root(self._parent[x])
		stack = [x]
		while self._parent[stack[-1]] != stack[-1]:
			stack.append(self._parent[stack[-1]])
		for v in stack:
			self._parent[v] = stack[-1]
		return self._parent[x]

	def unite(self, x, y):
		gx = self.find_root(x)
		gy = self.find_root(y)
		if gx == gy:
			return
		self.group -= 1
		if self._size[gx] < self._size[gy]:
			self._parent[gx] = gy
			self._size[gy] += self._size[gx]
		else:
			self._parent[gy] = gx
			self._size[gx] += self._size[gy]

	def get_size(self, x):
		return self._size[self.find_root(x)]

	def is_same_group(self, x, y):
		return self.find_root(x) == self.find_root(y)

class WeightedUnionFind:

	def __init__(self, N):
		self.parent = [i for i in range(N)]
		self.size = [1 for i in range(N)]
		self.val = [0 for i in range(N)]
		self.flag = True
		self.edge = [[] for i in range(N)]

	def dfs(self, v, pv):
		stack = [(v, pv)]
		new_parent = self.parent[pv]
		while stack:
			(v, pv) = stack.pop()
			self.parent[v] = new_parent
			for (nv, w) in self.edge[v]:
				if nv != pv:
					self.val[nv] = self.val[v] + w
					stack.append((nv, v))

	def unite(self, x, y, w):
		if not self.flag:
			return
		if self.parent[x] == self.parent[y]:
			self.flag = self.val[x] - self.val[y] == w
			return
		if self.size[self.parent[x]] > self.size[self.parent[y]]:
			self.edge[x].append((y, -w))
			self.edge[y].append((x, w))
			self.size[x] += self.size[y]
			self.val[y] = self.val[x] - w
			self.dfs(y, x)
		else:
			self.edge[x].append((y, -w))
			self.edge[y].append((x, w))
			self.size[y] += self.size[x]
			self.val[x] = self.val[y] + w
			self.dfs(x, y)

class Dijkstra:

	class Edge:

		def __init__(self, _to, _cost):
			self.to = _to
			self.cost = _cost

	def __init__(self, V):
		self.G = [[] for i in range(V)]
		self._E = 0
		self._V = V

	@property
	def E(self):
		return self._E

	@property
	def V(self):
		return self._V

	def add_edge(self, _from, _to, _cost):
		self.G[_from].append(self.Edge(_to, _cost))
		self._E += 1

	def shortest_path(self, s):
		import heapq
		inf = float('inf')
		que = []
		d = [inf] * self.V
		d[s] = 0
		heapq.heappush(que, (0, s))
		while len(que) != 0:
			(cost, v) = heapq.heappop(que)
			if d[v] < cost:
				continue
			for i in range(len(self.G[v])):
				e = self.G[v][i]
				if d[e.to] > d[v] + e.cost:
					d[e.to] = d[v] + e.cost
					heapq.heappush(que, (d[e.to], e.to))
		return d

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] < j:
			Z_alg[i + k] = Z_alg[k]
			k += 1
		i += k
		j -= k
	return Z_alg

class BIT:

	def __init__(self, n):
		self.BIT = [0] * (n + 1)
		self.num = n

	def query(self, idx):
		res_sum = 0
		while idx > 0:
			res_sum += self.BIT[idx]
			idx -= idx & -idx
		return res_sum

	def update(self, idx, x):
		while idx <= self.num:
			self.BIT[idx] += x
			idx += idx & -idx
		return

class dancinglink:

	def __init__(self, n, debug=False):
		self.n = n
		self.debug = debug
		self._left = [i - 1 for i in range(n)]
		self._right = [i + 1 for i in range(n)]
		self.exist = [True for i in range(n)]

	def pop(self, k):
		if self.debug:
			assert self.exist[k]
		L = self._left[k]
		R = self._right[k]
		if L != -1:
			if R != self.n:
				(self._right[L], self._left[R]) = (R, L)
			else:
				self._right[L] = self.n
		elif R != self.n:
			self._left[R] = -1
		self.exist[k] = False

	def left(self, idx, k=1):
		if self.debug:
			assert self.exist[idx]
		res = idx
		while k:
			res = self._left[res]
			if res == -1:
				break
			k -= 1
		return res

	def right(self, idx, k=1):
		if self.debug:
			assert self.exist[idx]
		res = idx
		while k:
			res = self._right[res]
			if res == self.n:
				break
			k -= 1
		return res

class SparseTable:

	def __init__(self, A, merge_func, ide_ele):
		N = len(A)
		n = N.bit_length()
		self.table = [[ide_ele for i in range(n)] for i in range(N)]
		self.merge_func = merge_func
		for i in range(N):
			self.table[i][0] = A[i]
		for j in range(1, n):
			for i in range(0, N - 2 ** j + 1):
				f = self.table[i][j - 1]
				s = self.table[i + 2 ** (j - 1)][j - 1]
				self.table[i][j] = self.merge_func(f, s)

	def query(self, s, t):
		b = t - s + 1
		m = b.bit_length() - 1
		return self.merge_func(self.table[s][m], self.table[t - 2 ** m + 1][m])

class BinaryTrie:

	class node:

		def __init__(self, val):
			self.left = None
			self.right = None
			self.max = val

	def __init__(self):
		self.root = self.node(-10 ** 15)

	def append(self, key, val):
		pos = self.root
		for i in range(29, -1, -1):
			pos.max = max(pos.max, val)
			if key >> i & 1:
				if pos.right is None:
					pos.right = self.node(val)
					pos = pos.right
				else:
					pos = pos.right
			elif pos.left is None:
				pos.left = self.node(val)
				pos = pos.left
			else:
				pos = pos.left
		pos.max = max(pos.max, val)

	def search(self, M, xor):
		res = -10 ** 15
		pos = self.root
		for i in range(29, -1, -1):
			if pos is None:
				break
			if M >> i & 1:
				if xor >> i & 1:
					if pos.right:
						res = max(res, pos.right.max)
					pos = pos.left
				else:
					if pos.left:
						res = max(res, pos.left.max)
					pos = pos.right
			elif xor >> i & 1:
				pos = pos.right
			else:
				pos = pos.left
		if pos:
			res = max(res, pos.max)
		return res

def solveequation(edge, ans, n, m):
	x = [0] * m
	used = [False] * n
	for v in range(n):
		if used[v]:
			continue
		y = dfs(v)
		if y != 0:
			return False
	return x

	def dfs(v):
		used[v] = True
		r = ans[v]
		for (to, dire, id) in edge[v]:
			if used[to]:
				continue
			y = dfs(to)
			if dire == -1:
				x[id] = y
			else:
				x[id] = -y
			r += y
		return r

class Matrix:
	mod = 10 ** 9 + 7

	def set_mod(m):
		Matrix.mod = m

	def __init__(self, L):
		self.row = len(L)
		self.column = len(L[0])
		self._matrix = L
		for i in range(self.row):
			for j in range(self.column):
				self._matrix[i][j] %= Matrix.mod

	def __getitem__(self, item):
		if type(item) == int:
			raise IndexError('you must specific row and column')
		elif len(item) != 2:
			raise IndexError('you must specific row and column')
		(i, j) = item
		return self._matrix[i][j]

	def __setitem__(self, item, val):
		if type(item) == int:
			raise IndexError('you must specific row and column')
		elif len(item) != 2:
			raise IndexError('you must specific row and column')
		(i, j) = item
		self._matrix[i][j] = val

	def __add__(self, other):
		if (self.row, self.column) != (other.row, other.column):
			raise SizeError('sizes of matrixes are different')
		res = [[0 for j in range(self.column)] for i in range(self.row)]
		for i in range(self.row):
			for j in range(self.column):
				res[i][j] = self._matrix[i][j] + other._matrix[i][j]
				res[i][j] %= Matrix.mod
		return Matrix(res)

	def __sub__(self, other):
		if (self.row, self.column) != (other.row, other.column):
			raise SizeError('sizes of matrixes are different')
		res = [[0 for j in range(self.column)] for i in range(self.row)]
		for i in range(self.row):
			for j in range(self.column):
				res[i][j] = self._matrix[i][j] - other._matrix[i][j]
				res[i][j] %= Matrix.mod
		return Matrix(res)

	def __mul__(self, other):
		if type(other) != int:
			if self.column != other.row:
				raise SizeError('sizes of matrixes are different')
			res = [[0 for j in range(other.column)] for i in range(self.row)]
			for i in range(self.row):
				for j in range(other.column):
					temp = 0
					for k in range(self.column):
						temp += self._matrix[i][k] * other._matrix[k][j]
					res[i][j] = temp % Matrix.mod
			return Matrix(res)
		else:
			n = other
			res = [[n * self._matrix[i][j] % Matrix.mod for j in range(self.column)] for i in range(self.row)]
			return Matrix(res)

	def __pow__(self, m):
		if self.column != self.row:
			raise MatrixPowError('the size of row must be the same as that of column')
		n = self.row
		res = Matrix([[int(i == j) for i in range(n)] for j in range(n)])
		while m:
			if m % 2 == 1:
				res = res * self
			self = self * self
			m //= 2
		return res

	def __str__(self):
		res = []
		for i in range(self.row):
			for j in range(self.column):
				res.append(str(self._matrix[i][j]))
				res.append(' ')
			res.append('\n')
		res = res[:len(res) - 1]
		return ''.join(res)

class SegmentTree:

	def __init__(self, init_val, segfunc, ide_ele):
		n = len(init_val)
		self.segfunc = segfunc
		self.ide_ele = ide_ele
		self.num = 1 << (n - 1).bit_length()
		self.tree = [ide_ele] * 2 * self.num
		for i in range(n):
			self.tree[self.num + i] = init_val[i]
		for i in range(self.num - 1, 0, -1):
			self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

	def update(self, k, x):
		k += self.num
		self.tree[k] = x
		while k > 1:
			self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
			k >>= 1

	def query(self, l, r):
		res = self.ide_ele
		l += self.num
		r += self.num
		while l < r:
			if l & 1:
				res = self.segfunc(res, self.tree[l])
				l += 1
			if r & 1:
				res = self.segfunc(res, self.tree[r - 1])
			l >>= 1
			r >>= 1
		return res

	def bisect_l(self, l, r, x):
		l += self.num
		r += self.num
		Lmin = -1
		Rmin = -1
		while l < r:
			if l & 1:
				if self.tree[l] <= x and Lmin == -1:
					Lmin = l
				l += 1
			if r & 1:
				if self.tree[r - 1] <= x:
					Rmin = r - 1
			l >>= 1
			r >>= 1
		if Lmin != -1:
			pos = Lmin
			while pos < self.num:
				if self.tree[2 * pos] <= x:
					pos = 2 * pos
				else:
					pos = 2 * pos + 1
			return pos - self.num
		elif Rmin != -1:
			pos = Rmin
			while pos < self.num:
				if self.tree[2 * pos] <= x:
					pos = 2 * pos
				else:
					pos = 2 * pos + 1
			return pos - self.num
		else:
			return -1

class DualSegmentTree:

	def __init__(self, n, segfunc, ide_ele):
		self.segfunc = segfunc
		self.ide_ele = ide_ele
		self.num = 1 << (n - 1).bit_length()
		self.tree = [ide_ele] * 2 * self.num

	def update(self, l, r, x):
		l += self.num
		r += self.num
		while l < r:
			if l & 1:
				self.tree[l] = self.segfunc(self.tree[l], x)
				l += 1
			if r & 1:
				self.tree[r - 1] = self.segfunc(self.tree[r - 1], x)
			l >>= 1
			r >>= 1

	def __getitem__(self, idx):
		idx += self.num
		res = self.ide_ele
		while idx:
			res = self.segfunc(res, self.tree[idx])
			idx >>= 1
		return res

class LazySegmentTree:
	__slots__ = ['merge', 'merge_unit', 'operate', 'merge_operate', 'operate_unit', 'n', 'data', 'lazy']

	def __init__(self, n, init, merge, merge_unit, operate, merge_operate, operate_unit):
		self.merge = merge
		self.merge_unit = merge_unit
		self.operate = operate
		self.merge_operate = merge_operate
		self.operate_unit = operate_unit
		self.n = (n - 1).bit_length()
		self.data = [merge_unit for i in range(1 << self.n + 1)]
		self.lazy = [operate_unit for i in range(1 << self.n + 1)]
		if init:
			for i in range(n):
				self.data[2 ** self.n + i] = init[i]
			for i in range(2 ** self.n - 1, 0, -1):
				self.data[i] = self.merge(self.data[2 * i], self.data[2 * i + 1])

	def propagate(self, v):
		ope = self.lazy[v]
		if ope == self.operate_unit:
			return
		self.lazy[v] = self.operate_unit
		self.data[v << 1] = self.operate(self.data[v << 1], ope)
		self.data[(v << 1) + 1] = self.operate(self.data[(v << 1) + 1], ope)
		self.lazy[v << 1] = self.merge_operate(self.lazy[v << 1], ope)
		self.lazy[(v << 1) + 1] = self.merge_operate(self.lazy[(v << 1) + 1], ope)

	def propagate_above(self, i):
		m = i.bit_length() - 1
		for bit in range(m, 0, -1):
			v = i >> bit
			self.propagate(v)

	def remerge_above(self, i):
		while i:
			c = self.merge(self.data[i], self.data[i ^ 1])
			i >>= 1
			self.data[i] = self.operate(c, self.lazy[i])

	def update(self, l, r, x):
		l += 1 << self.n
		r += 1 << self.n
		l0 = l // (l & -l)
		r0 = r // (r & -r) - 1
		self.propagate_above(l0)
		self.propagate_above(r0)
		while l < r:
			if l & 1:
				self.data[l] = self.operate(self.data[l], x)
				self.lazy[l] = self.merge_operate(self.lazy[l], x)
				l += 1
			if r & 1:
				self.data[r - 1] = self.operate(self.data[r - 1], x)
				self.lazy[r - 1] = self.merge_operate(self.lazy[r - 1], x)
			l >>= 1
			r >>= 1
		self.remerge_above(l0)
		self.remerge_above(r0)

	def query(self, l, r):
		l += 1 << self.n
		r += 1 << self.n
		l0 = l // (l & -l)
		r0 = r // (r & -r) - 1
		self.propagate_above(l0)
		self.propagate_above(r0)
		res = self.merge_unit
		while l < r:
			if l & 1:
				res = self.merge(res, self.data[l])
				l += 1
			if r & 1:
				res = self.merge(res, self.data[r - 1])
			l >>= 1
			r >>= 1
		return res

	def bisect_l(self, l, r, x):
		l += 1 << self.n
		r += 1 << self.n
		l0 = l // (l & -l)
		r0 = r // (r & -r) - 1
		self.propagate_above(l0)
		self.propagate_above(r0)
		Lmin = -1
		Rmin = -1
		while l < r:
			if l & 1:
				if self.data[l][0] <= x and Lmin == -1:
					Lmin = l
				l += 1
			if r & 1:
				if self.data[r - 1][0] <= x:
					Rmin = r - 1
			l >>= 1
			r >>= 1
		res = -1
		if Lmin != -1:
			pos = Lmin
			while pos < self.num:
				self.propagate(pos)
				if self.data[2 * pos][0] <= x:
					pos = 2 * pos
				else:
					pos = 2 * pos + 1
			res = pos - self.num
		if Rmin != -1:
			pos = Rmin
			while pos < self.num:
				self.propagate(pos)
				if self.data[2 * pos][0] <= x:
					pos = 2 * pos
				else:
					pos = 2 * pos + 1
			if res == -1:
				res = pos - self.num
			else:
				res = min(res, pos - self.num)
		return res

def floor_sum(n: int, m: int, a: int, b: int) -> int:
	ans = 0
	if a >= m:
		ans += (n - 1) * n * (a // m) // 2
		a %= m
	if b >= m:
		ans += n * (b // m)
		b %= m
	y_max = (a * n + b) // m
	x_max = y_max * m - b
	if y_max == 0:
		return ans
	ans += (n - (x_max + a - 1) // a) * y_max
	ans += floor_sum(y_max, a, m, (a - x_max % a) % a)
	return ans
import sys
from collections import deque, defaultdict
from heapq import heapify, heappop, heappush
from itertools import permutations
from math import log, gcd
input = lambda : sys.stdin.readline().rstrip()
mi = lambda : map(int, input().split())
li = lambda : list(mi())
(n, m) = mi()
s = input()
t = input()
top_pos = [-1 for i in range(m)]
find = 0
for i in range(n):
	if find != m and s[i] == t[find]:
		top_pos[find] = i
		find += 1
back_pos = [-1 for i in range(m)]
find = m - 1
for i in range(n - 1, -1, -1):
	if find != -1 and s[i] == t[find]:
		back_pos[find] = i
		find -= 1
ans = 0
for i in range(m - 1):
	a = top_pos[i]
	b = back_pos[i + 1]
	ans = max(ans, b - a)
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
l = []
r = []
j = 0
for i in range(n):
	if j == len(t):
		break
	if s[i] == t[j]:
		l.append(i)
		j += 1
j = len(t) - 1
for i in range(n - 1, -1, -1):
	if j == -1:
		break
	if s[i] == t[j]:
		r.append(i)
		j -= 1
r.reverse()
max = 0
for i in range(1, m):
	if int(r[i]) - int(l[i - 1]) > max:
		max = int(r[i]) - int(l[i - 1])
print(max)


(n, m) = map(int, input().split())
s = input()
t = input()
start = 1000000 * [0]
end = 1000000 * [0]
j = 0
for i in range(n):
	if j == m:
		break
	if t[j] == s[i]:
		start[j] = i
		j += 1
j = m - 1
for i in range(n - 1, -1, -1):
	if j == -1:
		break
	if t[j] == s[i]:
		end[j] = i
		j -= 1
ans = -1
for i in range(1, m):
	ans = max(ans, abs(end[i] - start[i - 1]))
print(ans)


from collections import deque, Counter
from math import sqrt, ceil, factorial
from sys import stdin, stdout
import sys
sys.setrecursionlimit(10 ** 7)
MOD = 10 ** 9 + 7
inf = float('inf')
ans_ = []

def inp():
	return int(input())

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

def readfl():
	return list(map(float, input().strip().split()))

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

def solve():
	(n, m) = read()
	s = input()
	t = input()
	c = 0
	fir = [0 for x in range(m)]
	sec = [0 for x in range(m)]
	for i in range(m):
		while s[c] != t[i]:
			c += 1
		fir[i] = c
		c += 1
	c = n - 1
	for i in range(m - 1, -1, -1):
		while s[c] != t[i]:
			c -= 1
		sec[i] = c
		c -= 1
	val = -1
	for i in range(m - 1):
		val = max(val, sec[i + 1] - fir[i])
	ans_.append(val)
solve()
for i in ans_:
	print(i)


def findmax(s, t):
	l_indexies = []
	start = 0
	for c in t:
		idx = s.find(c, start)
		l_indexies.append(idx)
		start = idx + 1
	r_indexies = []
	end = len(s)
	for c in reversed(t):
		idx = s.rfind(c, 0, end)
		r_indexies.append(idx)
		end = idx
	r_indexies = r_indexies[::-1]
	diff1 = (r - l for (l, r) in zip(l_indexies[:-1], l_indexies[1:]))
	diff2 = (r - l for (l, r) in zip(l_indexies[:-1], r_indexies[1:]))
	maxwidth = max(*diff1, *diff2)
	return maxwidth
(n, m) = list(map(int, input().split(' ')))
s = input()
t = input()
print(findmax(s, t))


def findMaxWidth():
	(n, m) = input().split(' ')
	big = input()
	small = input()
	posdict = {}
	for letter in small:
		posdict[letter] = []
	for index in range(len(big)):
		if big[index] in posdict.keys():
			posdict[big[index]].append(index)
	maxi = 0
	if len(posdict.keys()) > 1:
		print(posdict)
		for i in range(len(small) - 1):
			while posdict[small[i]][-1] > posdict[small[i + 1]][-1]:
				posdict[small[i]].pop()
		print(posdict)
		for i in range(len(small) - 1):
			width = posdict[small[i + 1]][-1] - posdict[small[i]][0]
			if width > maxi:
				maxi = width
	else:
		maxi = posdict[small[0]][-(len(small) - 1)] - posdict[small[0]][0]
	print(maxi)

def ans():
	(n, m) = map(int, input().split())
	s = list(input())
	t = list(input())
	pre = [0] * m
	suf = [0] * m
	j = 0
	for i in range(m):
		while s[j] != t[i]:
			j += 1
		pre[i] = j
		j += 1
	j = n - 1
	for i in range(m - 1, -1, -1):
		while s[j] != t[i]:
			j -= 1
		suf[i] = j
		j -= 1
	ans = 0
	for i in range(m - 1):
		ans = max(ans, suf[i + 1] - pre[i])
	print(ans)
ans()


from collections import Counter, defaultdict, deque
import math
import sys
input = sys.stdin.readline

def solve():
	(a, b) = [int(x) for x in input().split()]
	s1 = input().strip()
	s2 = input().strip()
	mn = []
	p = 0
	for i in range(a):
		if s1[i] == s2[p]:
			p += 1
			mn.append(i)
		if p == b:
			break
	p = b - 1
	mx = []
	for i in range(a - 1, -1, -1):
		if s1[i] == s2[p]:
			p -= 1
			mx.append(i)
		if p == -1:
			break
	mx = mx[::-1]
	rec = 0
	for i in range(1, b):
		rec = max(mx[i] - mn[i - 1], rec)
	print(rec)
tt = 1
for test in range(tt):
	solve()


(a, b) = map(int, input().split())
s = input()
t = input()
l1 = len(s)
l2 = len(t)
p1 = []
pos1 = 0
pos2 = 0
while pos1 < l1 and pos2 < l2:
	if s[pos1] == t[pos2]:
		p1.append(pos1)
		pos2 += 1
	pos1 += 1
p2 = []
pos1 = l1 - 1
pos2 = l2 - 1
while pos1 >= 0 and pos2 >= 0:
	if s[pos1] == t[pos2]:
		p2.append(pos1)
		pos2 -= 1
	pos1 -= 1
p2.reverse()
ans = 0
for i in range(1, l2):
	ans = max(ans, p2[i] - p1[i - 1])
print(ans)


from functools import lru_cache
from collections import defaultdict

def solution():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	leftMost = [None] * len(t)
	j = 0
	for i in range(len(s)):
		if j < len(t) and s[i] == t[j]:
			leftMost[j] = i
			j += 1
	rightMost = [None] * len(t)
	j = len(t) - 1
	for i in range(len(s))[::-1]:
		if j >= 0 and s[i] == t[j]:
			rightMost[j] = i
			j -= 1
	mx = 0
	for i in range(1, len(leftMost)):
		ans = rightMost[i] - leftMost[i - 1]
		mx = max(mx, ans)
	print(mx)
solution()


from sys import stdin, exit
from bisect import bisect_left as bl, bisect_right as br
from itertools import accumulate
yes = lambda : print('YES')
no = lambda : print('NO')
input = lambda : stdin.readline()[:-1]
intput = lambda : int(input())
sinput = lambda : input().split()
intsput = lambda : map(int, sinput())

def dprint(*args, **kwargs):
	if debugging:
		print(*args, **kwargs)
debugging = 1
(n, m) = intsput()
s = input()
t = input()
forward = []
pos = 0
for i in range(len(t)):
	target = t[i]
	for j in range(pos, len(s)):
		if s[j] == target:
			break
	forward.append(j)
	pos = j + 1
backward = []
pos = len(s) - 1
for i in range(len(t) - 1, -1, -1):
	target = t[i]
	for j in range(pos, -1, -1):
		if s[j] == target:
			break
	backward.append(j)
	pos = j - 1
backward = backward[::-1]
best = -float('inf')
for i in range(len(forward) - 1):
	x = forward[i]
	y = backward[i + 1]
	best = max(best, y - x)
print(best)


def solve(s, t):
	ans = []
	for (i, c) in enumerate(s):
		if c == t[len(ans)]:
			ans.append(i)
		if len(ans) == len(t):
			break
	return ans

def main():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	ans = 0
	first_s = solve(s, t)
	last_s = [n - i - 1 for i in solve(s[::-1], t[::-1])]
	last_s.reverse()
	for i in range(m - 1):
		ans = max(ans, last_s[i] - first_s[i + 1], last_s[i + 1] - first_s[i])
	print(ans)
main()


import sys, math, itertools, random, bisect
from collections import defaultdict
INF = sys.maxsize

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def get_array():
	return list(map(int, sys.stdin.readline().strip().split()))

def input():
	return sys.stdin.readline().strip()
mod = 10 ** 9 + 7
for _ in range(1):
	(n, m) = get_ints()
	s = input()
	t = input()
	left = [0] * m
	right = [0] * m
	(i, j) = (0, 0)
	while j < m:
		while s[i] != t[j]:
			i += 1
		left[j] = i
		i += 1
		j += 1
	i = n - 1
	j = m - 1
	while j >= 0:
		while s[i] != t[j]:
			i -= 1
		right[j] = i
		i -= 1
		j -= 1
	ans = 0
	for i in range(1, m):
		ans = max(ans, right[i] - left[i - 1])
	print(ans)


answers = []

def solve(n, m, s, t):
	if n == m:
		print(1)
		return
	first = []
	second = []
	current = 0
	for i in range(n):
		if s[i] == t[current]:
			first.append(i)
			current += 1
			if current == m:
				break
	current = m - 1
	for i in range(n - 1, -1, -1):
		if s[i] == t[current]:
			second.append(i)
			current -= 1
			if current == -1:
				break
	second.reverse()
	ans = 0
	for i in range(1, m):
		current = max(first[i] - first[i - 1], first[i] - second[i - 1], second[i] - second[i - 1], second[i] - first[i - 1])
		ans = max(ans, current)
	print(ans)
(n, m) = [int(x) for x in input().split()]
s = input()
t = input()
solve(n, m, s, t)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline()

def RL():
	return map(int, sys.stdin.readline().split())

def RLL():
	return list(map(int, sys.stdin.readline().split()))

def N():
	return int(input())

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

def print_list(l):
	print(' '.join(map(str, l)))
(n, m) = RL()
(s, t) = (S(), S())
l = []
k = -1
for c in t:
	k = s.index(c, k + 1)
	l.append(k)
k = n
ans = 0
for i in range(m - 1, 0, -1):
	k = s.rindex(t[i], 0, k)
	ans = max(ans, k - l[i - 1])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
ans = 0
f = [0] * m
l = [0] * m
q = 0
for i in range(n):
	if t[q] == s[i]:
		f[q] = i
		q += 1
	if q == m:
		break
q = m - 1
for i in range(n - 1, -1, -1):
	if t[q] == s[i]:
		l[q] = i
		q -= 1
	if q == -1:
		break
for i in range(1, m):
	ans = max(ans, l[i] - f[i - 1])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
forward = []
cur = 0
curr = 0
while curr < len(s) and cur < len(t):
	if s[curr] == t[cur]:
		forward.append(curr)
		cur += 1
	curr += 1
backward = []
cur = len(s) - 1
curr = len(t) - 1
while cur >= 0 and curr >= 0:
	if s[cur] == t[curr]:
		backward.append(cur)
		curr -= 1
	cur -= 1
backward = backward[::-1]
ans = 0
for i in range(1, len(t)):
	ans = max(ans, backward[i] - forward[i - 1], forward[i] - backward[i - 1])
print(ans)


(n, m) = [int(x) for x in input().split()]
s = input()
t = input()
n = len(s)
m = len(t)
p = []
j = 0
width = 0
for (i, x) in enumerate(t):
	j0 = j
	while s[j] != x:
		j += 1
	p += [j]
	j += 1
width = 0
for i in range(m - 1):
	if p[i + 1] - p[i] > width:
		width = p[i + 1] - p[i]
newpos = n - 1
for i in range(m - 1, 0, -1):
	oldpos = p[i]
	element = t[i]
	while True:
		if newpos == oldpos:
			newpos -= 1
			break
		if s[newpos] == element:
			p[i] = newpos
			if width < newpos - p[i - 1]:
				width = newpos - p[i - 1]
			newpos -= 1
			break
		else:
			newpos -= 1
print(width)


import os
import sys
from io import BytesIO, IOBase
from collections import Counter
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def gcd(a, b):
	if a == 0:
		return b
	return gcd(b % a, a)

def lcm(a, b):
	return a * b / gcd(a, b)

def main():
	(n, m) = map(int, input().split())
	S = input()
	T = input()
	s = []
	t = []
	for i in S:
		if ord('a') <= ord(i) <= ord('z'):
			s.append(i)
	for i in T:
		if ord('a') <= ord(i) <= ord('z'):
			t.append(i)
	fi = []
	se = []
	ind = 0
	for i in range(n):
		if ind >= m:
			break
		if s[i] == t[ind]:
			fi.append(i)
			ind += 1
	ind = m - 1
	for i in range(n - 1, -1, -1):
		if ind < 0:
			break
		if s[i] == t[ind]:
			se.append(i)
			ind -= 1
	ans = 0
	se.reverse()
	for i in range(m - 1):
		ans = max(se[i + 1] - fi[i], ans)
	print(ans)
	return
main()


from collections import deque
from typing import List

class ContestParser:

	def __init__(self):
		self.buffer = deque()

	def next_token(self) -> str:
		if len(self.buffer) == 0:
			self.buffer.extend(input().split())
		return self.buffer.popleft()

	def next_int(self) -> int:
		return int(self.next_token())

def find_greedily(haystack: str, needle: str) -> List[int]:
	result = []
	index = 0
	for c in needle:
		while haystack[index] != c:
			index += 1
		result.append(index)
		index += 1
	return result

def solve(s: str, t: str) -> int:
	n = len(s)
	m = len(t)
	first_indexes: List[int] = find_greedily(s, t)
	last_indexes: List[int] = list(reversed([n - idx - 1 for idx in find_greedily(list(reversed(s)), list(reversed(t)))]))
	result: int = 0
	for (idx, first_pos) in enumerate(first_indexes[:-1]):
		last_pos = last_indexes[idx + 1]
		result = max(result, last_pos - first_pos)
	return result
parser = ContestParser()
n = parser.next_int()
m = parser.next_int()
s = parser.next_token()
t = parser.next_token()
print(solve(s, t))


(n, m) = map(int, input().split())
val1 = input()
val2 = input()
left = []
right = []
num = m
for i in range(n - 1, -1, -1):
	vari = val1[i]
	if val2[num - 1] == vari:
		right.append(i)
		num = num - 1
	if num == 0:
		break
num = 0
for i in range(n):
	vari = val1[i]
	if val2[num] == vari:
		left.append(i)
		num += 1
	if num == m:
		break
result = 0
right.reverse()
for j in range(m - 1):
	result = max(right[j + 1] - left[j], result)
print(result)


from collections import defaultdict
(a, b) = list(map(int, input().split()))
s = input()
t = input()
mini = [-1] * a
maxi = [-1] * a
ind = 0
for i in range(a):
	if ind < b and s[i] == t[ind]:
		mini[ind] = i
		ind += 1
ind = b - 1
for i in range(a - 1, -1, -1):
	if ind >= 0 and s[i] == t[ind]:
		maxi[ind] = i
		ind -= 1
print(max([maxi[i] - mini[i - 1] for i in range(1, a)]))


from collections import defaultdict, OrderedDict, Counter
from sys import stdin, stdout
from bisect import bisect_left, bisect_right
from queue import Queue, PriorityQueue
from heapq import *
from statistics import *
from math import *
import fractions
import copy
from copy import deepcopy
import sys
import io
sys.setrecursionlimit(10000)
import math
import os
import bisect
import collections
mod = pow(10, 9) + 7
import random
from random import *
from time import time

def ncr(n, r, p=mod):
	num = den = 1
	for i in range(r):
		num = num * (n - i) % p
		den = den * (i + 1) % p
	return num * pow(den, p - 2, p) % p

def normalncr(n, r):
	r = min(r, n - r)
	count = 1
	for i in range(n - r, n + 1):
		count *= i
	for i in range(1, r + 1):
		count //= i
	return count
inf = float('inf')
adj = defaultdict(set)
visited = defaultdict(int)

def addedge(a, b):
	adj[a].add(b)
	adj[b].add(a)

def bfs(v):
	q = Queue()
	q.put(v)
	visited[v] = 1
	while q.qsize() > 0:
		s = q.get_nowait()
		print(s)
		for i in adj[s]:
			if visited[i] == 0:
				q.put(i)
				visited[i] = 1

def dfs(v, visited):
	if visited[v] == 1:
		return
	visited[v] = 1
	print(v)
	for i in adj[v]:
		dfs(i, visited)

def reverse_bisect_right(a, x, lo=0, hi=None):
	if lo < 0:
		raise ValueError('lo must be non-negative')
	if hi is None:
		hi = len(a)
	while lo < hi:
		mid = (lo + hi) // 2
		if x > a[mid]:
			hi = mid
		else:
			lo = mid + 1
	return lo

def reverse_bisect_left(a, x, lo=0, hi=None):
	if lo < 0:
		raise ValueError('lo must be non-negative')
	if hi is None:
		hi = len(a)
	while lo < hi:
		mid = (lo + hi) // 2
		if x >= a[mid]:
			hi = mid
		else:
			lo = mid + 1
	return lo

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

def get_str_list_in_int():
	return [int(i) for i in list(input())]

def get_str_list():
	return list(input())

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

def input_int():
	return int(input())

def matrix(a, b):
	return [[0 for i in range(b)] for j in range(a)]

def swap(a, b):
	return (b, a)

def find_gcd(l):
	a = l[0]
	for i in range(len(l)):
		a = gcd(a, l[i])
	return a

def is_prime(n):
	sqrta = int(sqrt(n))
	for i in range(2, sqrta + 1):
		if n % i == 0:
			return 0
	return 1

def prime_factors(n):
	while n % 2 == 0:
		return [2] + prime_factors(n // 2)
	sqrta = int(sqrt(n))
	for i in range(3, sqrta + 1, 2):
		if n % i == 0:
			return [i] + prime_factors(n // i)
	return [n]

def p(a):
	if type(a) == str:
		print(a + '\n')
	else:
		print(str(a) + '\n')

def ps(a):
	if type(a) == str:
		print(a)
	else:
		print(str(a))

def kth_no_not_div_by_n(n, k):
	return k + (k - 1) // (n - 1)

def forward_array(l):
	n = len(l)
	stack = []
	forward = [0] * n
	for i in range(len(l) - 1, -1, -1):
		while len(stack) and l[stack[-1]] < l[i]:
			stack.pop()
		if len(stack) == 0:
			forward[i] = len(l)
		else:
			forward[i] = stack[-1]
		stack.append(i)
	return forward

def backward_array(l):
	n = len(l)
	stack = []
	backward = [0] * n
	for i in range(len(l)):
		while len(stack) and l[stack[-1]] < l[i]:
			stack.pop()
		if len(stack) == 0:
			backward[i] = -1
		else:
			backward[i] = stack[-1]
		stack.append(i)
	return backward
nc = 'NO'
yc = 'YES'
ns = 'No'
ys = 'Yes'

def most_common(s, t):
	forward = [0] * len(t)
	backward = [0] * len(t)
	j = 0
	for i in range(len(s)):
		if j < m and s[i] == t[j]:
			backward[j] = i
			j += 1
	j = m - 1
	for i in reversed(range(len(s))):
		if j >= 0 and s[i] == t[j]:
			forward[j] = i
			j -= 1
	maxa = 1
	for i in range(m):
		maxa = max(maxa, forward[i] - backward[i - 1])
	return maxa
t = 1
for i in range(t):
	(n, m) = get_list()
	s = list(input())
	t = list(input())
	ans = most_common(s, t)
	print(ans)


import bisect
(n, m) = map(int, input().split())

def reverse_bisect_right(a, x, lo=0, hi=None):
	if lo < 0:
		raise ValueError('lo must be non-negative')
	if hi is None:
		hi = len(a)
	while lo < hi:
		mid = (lo + hi) // 2
		if x > a[mid]:
			hi = mid
		else:
			lo = mid + 1
	return lo
d = {}
s = list(input())
t = list(input())
for i in range(26):
	d[chr(ord('a') + i)] = []
for i in range(len(s)):
	d[s[i]].append(i)
mini = [d[t[0]][0]]
for i in range(1, len(t)):
	p = bisect.bisect_right(d[t[i]], mini[-1])
	mini.append(d[t[i]][p])
maxi = [-1 for i in range(m)]
maxi[-1] = d[t[-1]][-1]
temp_max = d[t[-1]][-1]
for i in d.keys():
	d[i] = d[i][::-1]
for i in range(len(t) - 2, -1, -1):
	p = reverse_bisect_right(d[t[i]], maxi[i + 1])
	maxi[i] = d[t[i]][p]
ans = 0
for i in range(1, len(t)):
	ans = max(ans, maxi[i] - mini[i - 1])
print(ans)


from sys import *
input = stdin.readline
(n, m) = map(int, input().split())
s = list(input())
t = list(input())
found = []
(idx, idy) = (m - 1, 0)
for i in range(n - 1, -1, -1):
	if idx >= 0:
		if s[i] == t[idx]:
			found.append(i)
			idx -= 1
found = found[::-1]
forw = []
for i in range(n):
	if idy < m:
		if s[i] == t[idy]:
			forw.append(i)
			idy += 1
ans = 0
for i in range(m - 1):
	ans = max(found[i + 1] - forw[i], ans)
print(ans)


import sys
input = sys.stdin.readline

def solve():
	(n, m) = map(int, input().split())
	p = [[] for i in range(26)]
	p1 = [None] * 26
	A = ord('a')
	j = 0
	for i in input().strip():
		p[ord(i) - A].append(j)
		j += 1
	for i in range(26):
		p1[i] = p[i].copy()
		p1[i].reverse()
	t = input().strip()
	a = []
	prev = -1
	for i in range(0, len(t)):
		c = ord(t[i]) - A
		while True:
			v = p1[c].pop()
			if v > prev:
				break
		a.append(v)
		prev = v
	b = []
	prev = int(1000000000.0)
	for i in range(len(t) - 1, -1, -1):
		c = ord(t[i]) - A
		while True:
			v = p[c].pop()
			if v < prev:
				break
		b.append(v)
		prev = v
	b.reverse()
	res = 0
	for i in range(1, len(t)):
		res = max(res, b[i] - a[i - 1])
	print(res)
solve()


from sys import stdin, stdout
input = stdin.readline

def main():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	ar = [0] * m
	ar2 = [0] * m
	ind = 0
	for i in range(m):
		while s[ind] != t[i]:
			ind += 1
		ar[i] = ind
		ind += 1
	ind = n - 1
	for i in range(m - 1, -1, -1):
		while s[ind] != t[i]:
			ind -= 1
		ar2[i] = ind
		ind -= 1
	ans = 0
	for i in range(1, m):
		ans = max(ans, ar[i] - ar[i - 1])
		ans = max(ans, ar2[i] - ar[i - 1])
		ans = max(ans, ar[i] - ar2[i - 1])
		ans = max(ans, ar2[i] - ar2[i - 1])
	print(ans)
main()


def main():
	(n, m) = map(int, input().split())
	s = input()
	t = input()
	a = ['' for i in range(m)]
	b = ['' for i in range(m)]
	i = 0
	j = 0
	while i < m:
		while t[i] != s[j]:
			j += 1
		a[i] = j
		i += 1
		j += 1
	t = t[::-1]
	s = s[::-1]
	j = 0
	i = 0
	while i < m:
		while t[i] != s[j]:
			j += 1
		b[i] = n - 1 - j
		i += 1
		j += 1
	b = b[::-1]
	print(max((b[i + 1] - a[i] for i in range(m - 1))))
main()


(n, m) = map(int, input().split())
s = input()
t = input()
a = []
b = []
k = 0
for i in range(n):
	if s[i] == t[k]:
		a.append(i)
		k += 1
	if k == m:
		break
k = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[k]:
		b.append(i)
		k -= 1
	if k == -1:
		break
b.reverse()
k = 0
for i in range(m):
	if i < m - 1:
		if b[i + 1] - a[i] > k:
			k = b[i + 1] - a[i]
print(k)


(n, m) = map(int, input().split())
s = input()
t = input()
if n == m:
	print(1)
else:
	left = [0] * m
	(i, j) = (0, 0)
	while j < m:
		if s[i] == t[j]:
			left[j] = i
			j += 1
		i += 1
	(i, j) = (n - 1, m - 1)
	res = 0
	while j > 0:
		if s[i] == t[j]:
			res = max(res, i - left[j - 1])
			j -= 1
		i -= 1
	print(res)


import bisect
import collections
import functools
import itertools
import math
import heapq
import random
import string

def repeat(_func=None, *, times=1):

	def decorator(func):

		@functools.wraps(func)
		def wrapper(*args, **kwargs):
			for _ in range(times):
				func(*args, **kwargs)
		return wrapper
	if _func is None:
		return decorator
	else:
		return decorator(_func)

def unpack(func=int):
	return map(func, input().split())

def l_unpack(func=int):
	return list(map(func, input().split()))

def getint():
	return int(input())

def getmatrix(rows):
	return [list(map(int, input().split())) for _ in range(rows)]

def display_matrix(mat):
	for i in range(len(mat)):
		print(mat[i])

def main():
	(n, m) = unpack()
	s = input()
	t = input()
	left = [0] * m
	right = [0] * m
	pos = 0
	for (i, c) in enumerate(t):
		while s[pos] != c:
			pos += 1
		left[i] = pos
		pos += 1
	pos = n - 1
	for i in range(m - 1, -1, -1):
		while s[pos] != t[i]:
			pos -= 1
		right[i] = pos
		pos -= 1
	ans = 1
	for i in range(m - 1):
		ans = max(ans, right[i + 1] - left[i])
	print(ans)
MOD = 10 ** 9 + 7
main()


(n, m) = map(int, input().split())
s = input()
t = input()
nxt = [0 for i in range(m)]
lst = [0 for i in range(m)]
j = 0
for i in range(n):
	if j < m and s[i] == t[j]:
		nxt[j] = i
		j = j + 1
j = m - 1
for i in range(n - 1, -1, -1):
	if j >= 0 and s[i] == t[j]:
		lst[j] = i
		j = j - 1
mx = 0
for i in range(m - 1):
	mx = max(mx, lst[i + 1] - nxt[i])
print(mx)


from sys import stdin, stdout
from math import gcd, sqrt, factorial, pi, inf
from collections import deque, defaultdict
from bisect import bisect, bisect_left
from itertools import permutations as per
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\n')
L = lambda : list(R())
P = lambda x: stdout.write(str(x) + '\n')
nCr = lambda x, y: f[x] * inv(f[y] * f[x - y] % N) % N
inv = lambda x: pow(x, N - 2, N)
lcm = lambda x, y: x * y // gcd(x, y)
hg = lambda x, y: (y + x - 1) // x * x
pw = lambda x: 1 if x == 1 else 1 + pw(x // 2)
chk = lambda x: chk(x // 2) if not x % 2 else True if x == 1 else False
sm = lambda x: (x ** 2 + x) // 2
N = 10 ** 9 + 7

def get_indx(a, r, val):
	l = 0
	ans = 0
	while l <= r:
		m = (l + r) // 2
		if a[m] < val:
			ans = a[m]
			l = m + 1
		else:
			r = m - 1
	return ans

def get_ind(a, r, val):
	l = 0
	ans = 0
	while l <= r:
		m = (l + r) // 2
		if a[m] > val:
			ans = a[m]
			r = m - 1
		else:
			l = m + 1
	return ans
(n, m) = R()
v = [[] for i in range(26)]
ln = [0] * 26
for (i, j) in enumerate([ord(i) - 97 for i in S()]):
	v[j] += (i,)
	ln[j] += 1
s = [ord(i) - 97 for i in S()]
a = [0] * m
p = -1
for i in range(m - 1):
	a[i] = get_ind(v[s[i]], ln[s[i]] - 1, p)
	p = a[i]
a[-1] = v[s[-1]][-1]
ans = a[-1] - a[-2]
for i in range(m - 2, 0, -1):
	a[i] = get_indx(v[s[i]], ln[s[i]] - 1, a[i + 1])
	ans = max(ans, a[i] - a[i - 1])
print(ans)


import sys
import heapq
import math
from collections import deque
MOD = 1000000007

def primes(n):
	sieve = [True] * n
	for i in range(3, int(n ** 0.5) + 1, 2):
		if sieve[i]:
			sieve[i * i::2 * i] = [False] * ((n - i * i - 1) // (2 * i) + 1)
	return [2] + [i for i in range(3, n, 2) if sieve[i]]

def factor(n, l, d):
	F = False
	for p in l:
		if n % p == 0:
			if p in d:
				d[p] += 1
			else:
				d[p] = 1
			F = True
			break
	if F:
		factor(n // p, l, d)

def find(parent, i):
	if parent[i] != i:
		parent[i] = find(parent, parent[i])
	return parent[i]

def union(parent, rank, xx, yy):
	x = find(parent, xx)
	y = find(parent, yy)
	if rank[x] > rank[y]:
		parent[y] = x
	elif rank[y] > rank[x]:
		parent[x] = y
	else:
		parent[y] = x
		rank[x] += 1
ans = 0
NQ = sys.stdin.readline().strip().split()
S = sys.stdin.readline().strip()
T = sys.stdin.readline().strip()
l = []
r = []
d = {}
for i in range(len(S)):
	if S[i] not in d:
		d[S[i]] = [i]
	else:
		d[S[i]].append(i)
c = -1
i = 0
while i < len(T):
	c += 1
	while S[c] != T[i]:
		c += 1
	l.append(c)
	i += 1
c = len(S)
for i in range(len(T) - 1, -1, -1):
	c -= 1
	while S[c] != T[i]:
		c -= 1
	r.append(c)
r.reverse()
ans = 0
for i in range(len(T) - 1):
	ans = max(ans, r[i + 1] - l[i])
print(ans)
dd = {'R': 'L', 'L': 'R'}
l = [0, 0, 1, 1, 3]

def tv(i, j, w):
	ma = -1
	mi = -1
	if i == j:
		return
	for k in range(i, j):
		if l[k] > ma:
			ma = l[k]
			mi = k
	ans[mi] = str(w)
	tv(i, mi, w + 1)
	tv(mi + 1, j, w + 1)
l = []
s = set()


from sys import stdin, stdout
from collections import defaultdict
import math

def high():
	return math.inf

def low():
	return 0
(n, m) = list(map(int, stdin.readline().split()))
count = 0
s1 = stdin.readline()
s2 = stdin.readline()
min_dict = defaultdict(high)
max_dict = defaultdict(low)
ind = 0
for i in range(n):
	if ind < m and s1[i] == s2[ind]:
		min_dict[ind] = i
		ind += 1
ind = m - 1
for i in range(n - 1, -1, -1):
	if ind > -1 and s1[i] == s2[ind]:
		max_dict[ind] = i
		ind -= 1
for i in range(1, m):
	count = max(count, max_dict[i] - min_dict[i - 1])
print(max(count, 1))


import os
import sys
import math
from io import BytesIO, IOBase
from fractions import Fraction
import collections
from itertools import permutations
from collections import defaultdict
from collections import deque
import threading
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class SegmentTree:

	def __init__(self, data, default=-10 ** 6, func=lambda a, b: max(a, b)):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree1:

	def __init__(self, data, default=10 ** 6, func=lambda a, b: min(a, b)):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)
MOD = 10 ** 9 + 7

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD
mod = 10 ** 9 + 7
omod = 998244353
prime = [True for i in range(200001)]
pp = [0] * 200001

def SieveOfEratosthenes(n=200000):
	p = 2
	while p * p <= n:
		if prime[p] == True:
			for i in range(p * p, n + 1, p):
				prime[i] = False
		p += 1
(n, m) = map(int, input().split())
s = input()
t = input()
pre = [0] * m
post = [0] * m
j = 0
for i in range(m):
	while s[j] != t[i]:
		j += 1
	j += 1
	pre[i] = j
j = n - 1
for i in range(m - 1, -1, -1):
	while s[j] != t[i]:
		j -= 1
	post[i] = j + 1
	j -= 1
mx = 0
for i in range(1, m):
	mx = max(mx, post[i] - pre[i - 1])
print(mx)


import os
import sys
from io import BytesIO, IOBase
import math
import itertools
import bisect

def main():
	pass
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def binary(n):
	return bin(n).replace('0b', '')

def decimal(s):
	return int(s, 2)

def pow2(n):
	p = 0
	while n > 1:
		n //= 2
		p += 1
	return p

def primeFactors(n):
	l = []
	while n % 2 == 0:
		l.append(2)
		n = n / 2
	for i in range(3, int(math.sqrt(n)) + 1, 2):
		while n % i == 0:
			l.append(i)
			n = n / i
	if n > 2:
		l.append(int(n))
	return l

def isPrime(n):
	if n == 1:
		return False
	else:
		root = int(n ** 0.5)
		root += 1
		for i in range(2, root):
			if n % i == 0:
				return False
		return True

def maxPrimeFactors(n):
	maxPrime = -1
	while n % 2 == 0:
		maxPrime = 2
		n >>= 1
	for i in range(3, int(math.sqrt(n)) + 1, 2):
		while n % i == 0:
			maxPrime = i
			n = n / i
	if n > 2:
		maxPrime = n
	return int(maxPrime)

def countcon(s, i):
	c = 0
	ch = s[i]
	for i in range(i, len(s)):
		if s[i] == ch:
			c += 1
		else:
			break
	return c

def lis(arr):
	n = len(arr)
	lis = [1] * n
	for i in range(1, n):
		for j in range(0, i):
			if arr[i] > arr[j] and lis[i] < lis[j] + 1:
				lis[i] = lis[j] + 1
	maximum = 0
	for i in range(n):
		maximum = max(maximum, lis[i])
	return maximum

def isSubSequence(str1, str2):
	m = len(str1)
	n = len(str2)
	j = 0
	i = 0
	while j < m and i < n:
		if str1[j] == str2[i]:
			j = j + 1
		i = i + 1
	return j == m

def maxfac(n):
	root = int(n ** 0.5)
	for i in range(2, root + 1):
		if n % i == 0:
			return n // i
	return n

def p2(n):
	c = 0
	while n % 2 == 0:
		n //= 2
		c += 1
	return c

def seive(n):
	primes = [True] * (n + 1)
	primes[1] = primes[0] = False
	for i in range(2, n + 1):
		if primes[i]:
			for j in range(i + i, n + 1, i):
				primes[j] = False
	p = []
	for i in range(0, n + 1):
		if primes[i]:
			p.append(i)
	return p

def ncr(n, r, p):
	num = den = 1
	for i in range(r):
		num = num * (n - i) % p
		den = den * (i + 1) % p
	return num * pow(den, p - 2, p) % p

def denofactinverse(n, m):
	fac = 1
	for i in range(1, n + 1):
		fac = fac * i % m
	return pow(fac, m - 2, m)

def numofact(n, m):
	fac = 1
	for i in range(1, n + 1):
		fac = fac * i % m
	return fac

def chk(n, d):
	if str(d) in str(n):
		return True
	return False
(n, m) = map(int, input().split())
s = input()
t = input()
lftmost = []
rgtmost = []
i = j = 0
while j < m:
	if s[i] == t[j]:
		j += 1
		lftmost.append(i)
	i += 1
(i, j) = (n - 1, m - 1)
while j >= 0:
	if s[i] == t[j]:
		j -= 1
		rgtmost.append(i)
	i -= 1
rgtmost = rgtmost[::-1]
ans = 1
for i in range(1, m):
	ans = max(ans, rgtmost[i] - lftmost[i - 1])
print(ans)


def main():
	inp = input().rstrip().split(' ')
	(n, m) = (int(inp[0]), int(inp[1]))
	s = input().rstrip()
	t = input().rstrip()
	fwd_arr = [0 for i in range(m)]
	bwd_arr = [0 for i in range(m)]
	fpos = 0
	bpos = n - 1
	for i in range(m):
		while s[fpos] != t[i]:
			fpos += 1
		fwd_arr[i] = fpos
		fpos += 1
		while s[bpos] != t[m - 1 - i]:
			bpos -= 1
		bwd_arr[m - 1 - i] = bpos
		bpos -= 1
	ans = 0
	for i in range(m - 1):
		ans = max(ans, bwd_arr[i + 1] - fwd_arr[i])
	print(ans)
main()


(n, m) = map(int, input().split())
s = input()
t = input()

def a_to_i(x):
	return ord(x) - ord('a')
cur = 0
l = []
for i in range(n):
	if t[cur] == s[i]:
		l.append(i)
		cur += 1
	if cur == m:
		break
cur = m - 1
r = []
for i in range(n - 1, -1, -1):
	if t[cur] == s[i]:
		r.append(i)
		cur -= 1
	if cur == -1:
		break
r.reverse()
ans = 0
for i in range(m - 1):
	ans = max(ans, r[i + 1] - l[i])
print(ans)


from collections import defaultdict

def main():
	(n, m) = readIntArr()
	s = input()
	t = input()
	sIndices = defaultdict(lambda : [])
	for (i, c) in enumerate(s):
		sIndices[c].append(i)
	maxP = [None for _ in range(m)]
	minP = [None for _ in range(m)]
	cumuMinP = -inf
	for i in range(m):
		c = t[i]
		indexesArr = sIndices[c]
		l = len(indexesArr)
		b = l
		j = -1
		while b > 0:
			while j + b < l and indexesArr[j + b] < cumuMinP:
				j += b
			b //= 2
		j += 1
		minP[i] = indexesArr[j]
		cumuMinP = indexesArr[j]
		cumuMinP += 1
	cumuMaxP = inf
	for i in range(m - 1, -1, -1):
		c = t[i]
		indexesArr = sIndices[c]
		l = len(indexesArr)
		b = l
		j = l
		while b > 0:
			while j - b >= 0 and indexesArr[j - b] > cumuMaxP:
				j -= b
			b //= 2
		j -= 1
		maxP[i] = indexesArr[j]
		cumuMaxP = indexesArr[j]
		cumuMaxP -= 1
	ans = -inf
	for i in range(1, m):
		ans = max(ans, maxP[i] - minP[i - 1])
	print(ans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]
inf = float('inf')
MOD = 10 ** 9 + 7
main()


(n, m) = map(int, input().split())
s1 = input()
s2 = input()
left = dict()
right = dict()
l = 0
r = n - 1
for i in range(m):
	while s1[l] != s2[i]:
		l = l + 1
	left[i] = l
	l = l + 1
for i in range(m - 1, -1, -1):
	while s1[r] != s2[i]:
		r = r - 1
	right[i] = r
	r = r - 1
res = 0
for i in range(m - 1):
	res = max(res, right[i + 1] - left[i])
print(res)


import math
import heapq

def S():
	return input()

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

def I():
	return int(S())

def L():
	return list(M())
(n, m) = M()
s = S()
t = S()
(l, r) = ([0] * m, [0] * m)
(i, j) = (0, 0)
while j < m and i < n:
	if s[i] == t[j]:
		l[j] = i
		j += 1
	i += 1
(i, j) = (n - 1, m - 1)
while j >= 0 and i >= 0:
	if s[i] == t[j]:
		r[j] = i
		j -= 1
	i -= 1
a = []
for i in range(m - 1):
	a.append(r[i + 1] - l[i])
print(max(a))


import sys
input = sys.stdin.readline

def main():
	(N, M) = [int(x) for x in input().split()]
	S = input().strip()
	T = input().strip()
	aa = []
	current = 0
	for i in range(M):
		for j in range(current, N):
			if T[i] == S[j]:
				aa.append(j)
				current = j + 1
				break
	bb = []
	current = N - 1
	for i in range(M - 1, -1, -1):
		for j in range(current, -1, -1):
			if T[i] == S[j]:
				bb.append(j)
				current = j - 1
				break
	bb = bb[::-1]
	ans = 0
	for i in range(M - 1):
		ans = max(bb[i + 1] - aa[i], ans)
	print(ans)
main()


(n, m) = map(int, input().split())
s = input()
t = input()
j = 0
left = [-1] * (m + 1)
for i in range(m):
	while j < n and s[j] != t[i]:
		j += 1
	if j == n:
		break
	left[i + 1] = j
	j += 1
right = [-1] * (m + 1)
j = n - 1
for i in range(m - 1, -1, -1):
	while j >= 0 and s[j] != t[i]:
		j -= 1
	if j == -1:
		break
	right[m - 1 - i + 1] = j
	j -= 1
w = 0
for i in range(1, m, +1):
	w = max(w, right[m - i] - left[i])
print(w)


(n, m) = map(int, input().split())
s = input()
t = input()
s1 = []
s2 = []
j = 0
for i in range(m):
	while t[i] != s[j]:
		j += 1
	s1.append(j)
	j += 1
j = 0
s = s[::-1]
t = t[::-1]
for i in range(m):
	while t[i] != s[j]:
		j += 1
	s2.append(n - j - 1)
	j += 1
ans = 0
s2 = s2[::-1]
for i in range(m - 1):
	ans = max(ans, s2[i + 1] - s1[i])
print(ans)


import sys
import math
import random
from queue import PriorityQueue as PQ
from bisect import bisect_left as BSL
from bisect import bisect_right as BSR
from collections import OrderedDict as OD
from collections import Counter
from itertools import permutations
from decimal import Decimal as BIGFLOAT
mod = 1000000007
MOD = mod
try:
	sys.stdin = open('actext.txt', 'r')
	OPENFILE = 1
except:
	pass

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

def palindrome(s):
	mid = len(s) // 2
	for i in range(mid):
		if s[i] != s[len(s) - i - 1]:
			return False
	return True

def check(i, n):
	if 0 <= i < n:
		return True
	else:
		return False
(n, m) = get_ints()
s = input()
t = input()
mi = []
i = 0
j = 0
while j < m:
	if s[i] == t[j]:
		mi.append(i)
		j += 1
	i += 1
mx = []
i = n - 1
j = m - 1
while j >= 0:
	if t[j] == s[i]:
		mx.append(i)
		j -= 1
	i -= 1
mx.reverse()
ans = 0
for i in range(m - 1):
	ans = max(ans, mx[i + 1] - mi[i])
print(ans)


n = input()
s = list(input())
t = list(input())
pref = [0] * (len(s) + 1)
for i in range(1, len(s) + 1):
	if pref[i - 1] == len(t):
		pref[i] = len(t)
	elif t[pref[i - 1]] == s[i - 1]:
		pref[i] = pref[i - 1] + 1
	else:
		pref[i] = pref[i - 1]
ss = s[::-1]
tt = t[::-1]
pref2 = [0] * (len(ss) + 1)
for i in range(1, len(ss) + 1):
	if pref2[i - 1] == len(tt):
		pref2[i] = len(tt)
	elif tt[pref2[i - 1]] == ss[i - 1]:
		pref2[i] = pref2[i - 1] + 1
	else:
		pref2[i] = pref2[i - 1]
i = 0
while pref[i] == 0:
	i += 1
j = len(s)
ans = 0
while pref[i] < len(t):
	while pref2[j] >= len(t) - pref[i]:
		j -= 1
	j += 1
	ans = max(ans, len(s) - j - i + 1)
	x = pref[i]
	i += 1
	while i < len(s) and pref[i] == x:
		i += 1
print(ans)


class Solution:

	def solution(self, str1, str2):
		(n, m) = (len(str1), len(str2))
		first_position = [0] * m
		last_position = [0] * m
		i = 0
		for j in range(m):
			while i < n and str1[i] != str2[j]:
				i += 1
			if i >= n:
				break
			first_position[j] = i
			i += 1
		i = n - 1
		for j in range(m - 1, -1, -1):
			while i > -1 and str1[i] != str2[j]:
				i -= 1
			if i < 0:
				break
			last_position[j] = i
			i -= 1
		result = 1
		for i in range(m - 1):
			result = max(result, last_position[i + 1] - first_position[i])
		return result
(n, m) = map(int, input().split())
str1 = input()
str2 = input()
sol = Solution()
print(sol.solution(str1, str2))


def solve(s, t):
	min_ids = []
	i = 0
	for ct in t:
		while True:
			if s[i] == ct:
				min_ids.append(i)
				i += 1
				break
			i += 1
	max_ids = []
	i = len(s) - 1
	for ct in reversed(t):
		while True:
			if s[i] == ct:
				max_ids.append(i)
				i -= 1
				break
			i -= 1
	max_ids.reverse()
	mx = 0
	for (i, min_id) in enumerate(min_ids[:-1]):
		mx = max(max_ids[i + 1] - min_id, mx)
	print(mx)
input()
s = input().strip()
t = input().strip()
solve(s, t)


(n, m) = map(int, input().split())
s = list(input())
t = list(input())
pre = [0] * m
suf = [0] * m
j = 0
for i in range(m):
	while s[j] != t[i]:
		j += 1
	pre[i] = j
	j += 1
j = n - 1
for i in range(m - 1, -1, -1):
	while s[j] != t[i]:
		j -= 1
	suf[i] = j
	j -= 1
ans = 0
for i in range(m - 1):
	ans = max(ans, suf[i + 1] - pre[i])
print(ans)


from os import path
import sys, time
mod = int(1000000000.0 + 7)
from math import ceil, floor, gcd, log, log2, factorial, sqrt
from collections import defaultdict, Counter, OrderedDict, deque
from itertools import combinations, permutations, groupby
from bisect import *
from functools import reduce
from operator import mul
maxx = float('inf')
I = lambda : int(sys.stdin.buffer.readline())
lint = lambda : [int(x) for x in sys.stdin.buffer.readline().split()]
S = lambda : sys.stdin.readline().strip('\n')
localsys = 0
start_time = time.time()
nCr = lambda n, r: reduce(mul, range(n - r + 1, n + 1), 1) // factorial(r)

def ceill(n, x):
	return (n + x - 1) // x
T = 0

def solve():
	(n, m) = map(int, input().split())
	s = input().strip()
	t = input().strip()
	(i, l) = (0, [])
	for j in t:
		while s[i] != j:
			i += 1
		l.append(i)
		i += 1
	(i, r) = (n - 1, [])
	for c in t[::-1]:
		while s[i] != c:
			i -= 1
		r.append(i)
		i -= 1
	print(max((j - i for (i, j) in zip(l, r[::-1][1:]))))

def run():
	if path.exists('input.txt'):
		sys.stdin = open('input.txt', 'r')
		sys.stdout = open('output.txt', 'w')
		localsys = 1
run()
T = I() if T else 1
for _ in range(T):
	solve()
if localsys:
	print('\n\nTime Elased :', time.time() - start_time, 'seconds')


(n, m) = map(int, input().split())
s = list(input())
t = list(input())
left = []
i = 0
j = 0
while i < n and j < m:
	if s[i] == t[j]:
		left.append(i)
		i += 1
		j += 1
	else:
		i += 1
right = []
i = n - 1
j = m - 1
while i >= 0 and j >= 0:
	if s[i] == t[j]:
		right.append(i)
		i -= 1
		j -= 1
	else:
		i -= 1
right.reverse()
ans = 0
for i in range(m - 1):
	ans = max(ans, right[i + 1] - left[i])
print(ans)


from sys import stdin, stdout
from bisect import *
input = stdin.readline
from random import sample
t = 1
from collections import Counter
from math import sqrt, ceil

class DisjSet:

	def __init__(self, n):
		self.rank = [1] * n
		self.parent = [i for i in range(n)]

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		xset = self.find(x)
		yset = self.find(y)
		if xset == yset:
			return
		if self.rank[xset] < self.rank[yset]:
			self.parent[xset] = yset
		elif self.rank[xset] > self.rank[yset]:
			self.parent[yset] = xset
		else:
			self.parent[yset] = xset
			self.rank[xset] = self.rank[xset] + 1

def f(arr, i, j, d, dist):
	if i == j:
		return
	nn = max(arr[i:j])
	for tl in range(i, j):
		if arr[tl] == nn:
			dist[tl] = d
			f(arr, i, tl, d + 1, dist)
			f(arr, tl + 1, j, d + 1, dist)

def ps(n):
	cp = 0
	while n % 2 == 0:
		n = n // 2
		cp += 1
	for ps in range(3, ceil(sqrt(n)) + 1, 2):
		while n % ps == 0:
			n = n // ps
			cp += 1
	if n != 1:
		return False
	return True

def find_gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x

def factorials(n, r):
	slr = n
	dpr = r
	qlr = 1
	qs = 1
	mod = 10 ** 9 + 7
	for ip in range(n - r + 1, n + 1):
		qlr = qlr * ip % mod
	for ij in range(1, r + 1):
		qs = qs * ij % mod
	ans = qlr * modInverse(qs) % mod
	return ans

def modInverse(b):
	qr = 10 ** 9 + 7
	return pow(b, qr - 2, qr)
tt = [xa ** 3 for xa in range(0, 10 ** 4 + 1)]
qq = set(tt)
for jj in range(t):
	(n, m) = [int(x) for x in input().strip().split()]
	string = input()
	arr = list(string)
	string2 = input()
	miner = [0] * m
	maxer = [0] * m
	il = n - 1
	for i in range(m - 1, -1, -1):
		while string2[i] != string[il]:
			il -= 1
		maxer[i] = il
		il -= 1
	il = 0
	for i in range(m):
		while string2[i] != string[il]:
			il += 1
		miner[i] = il
		il += 1
	ans = 0
	for i in range(1, m):
		ans = max(maxer[i] - miner[i - 1], ans)
	print(ans)


def other(n, m, s, t):
	d = [0] * m
	i = 0
	j = 0
	while j < m:
		if s[i] == t[j]:
			d[j] = i
			j += 1
		i += 1
	e = [0] * m
	i = n - 1
	j = m - 1
	while j >= 0:
		if s[i] == t[j]:
			e[j] = i
			j -= 1
		i -= 1
	mm = 0
	for i in range(m - 1):
		if e[i + 1] - d[i] > mm:
			mm = e[i + 1] - d[i]
	return mm
(n, m) = map(int, input().split())
s = list(str(input()))
t = list(str(input()))
print(other(n, m, s, t))


(n, m) = [int(x) for x in input().split()]
s = input()
t = input()
L = 1
R = n - m + 1
head = 0
indices1 = []
indices2 = []
for i in range(n):
	if s[i] == t[head]:
		head += 1
		indices1.append(i)
	if head == m:
		break
tail = m - 1
for i in range(n):
	if s[n - 1 - i] == t[tail]:
		tail -= 1
		indices2.append(n - 1 - i)
	if tail == -1:
		break
indices2.reverse()
ans = max([indices2[i + 1] - indices1[i] for i in range(m - 1)])
print(ans)


import sys

def read_ints():
	return [int(i) for i in sys.stdin.readline().strip().split()]

def width(s, t):
	n = len(s)
	m = len(t)
	firsts = []
	j = 0
	for (i, c) in enumerate(t):
		while s[j] != c:
			j += 1
		firsts.append(j)
		j += 1
	lasts = []
	j = n - 1
	for i in range(m - 1, -1, -1):
		c = t[i]
		while s[j] != c:
			j -= 1
		lasts.append(j)
		j -= 1
	lasts.reverse()
	return max((a - b for (a, b) in zip(lasts[1:], firsts[:-1])))
(n, m) = read_ints()
s = sys.stdin.readline().strip()
t = sys.stdin.readline().strip()
print(width(s, t))


(n, m) = map(int, input().split())
s = input()
t = input()
S = []
T = []
j = 0
i = 0
while i < n and j < m:
	if s[i] == t[j]:
		S.append(i)
		j += 1
	i += 1
i = n - 1
j = m - 1
while i >= 0 and j >= 0:
	if s[i] == t[j]:
		T.append(i)
		j -= 1
	i -= 1
T = T[::-1]
ans = 0
for i in range(1, len(S)):
	ans = max(ans, T[i] - S[i - 1])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
ans = 0
startPos = s.find(t[0])
endPos = s.rfind(t[m - 1])
counter = 2
maxVals = [0 for i in range(m)]
minVals = [0 for i in range(m)]
minVals[0] = startPos
maxVals[m - 1] = endPos
for i in range(endPos - 1, startPos, -1):
	if s[i] == t[m - counter] and counter < m:
		maxVals[m - counter] = i
		counter += 1
counter = 1
for i in range(startPos + 1, endPos, 1):
	if s[i] == t[counter] and counter < m - 1:
		minVals[counter] = i
		counter += 1
for i in range(1, m):
	ans = max(ans, maxVals[i] - minVals[i - 1])
print(ans)


ch = input()
L = [int(i) for i in ch.split()]
(n, m) = (L[0], L[1])
c = input()
s = input()
g = [-1] * m
j = 0
for i in range(n):
	if c[i] == s[j]:
		g[j] = i
		j += 1
		if j >= m:
			break
d = [-1] * m
j = m - 1
for i in range(n - 1, -1, -1):
	if c[i] == s[j]:
		d[j] = i
		j -= 1
		if j < 0:
			break
maxx = 0
for i in range(1, m):
	maxx = max(maxx, d[i] - g[i - 1])
print(maxx)


(n, m) = map(int, input().split())
s = input()
t = input()
l = []
l1 = []
i = 0
j = 0
while i < n and j < m:
	if s[i] == t[j]:
		l.append(i + 1)
		i += 1
		j += 1
	else:
		i += 1
i = n - 1
j = m - 1
while i >= 0 and j >= 0:
	if s[i] == t[j]:
		l1.append(i + 1)
		i -= 1
		j -= 1
	else:
		i -= 1
l1.reverse()
mi = 0
for i in range(len(l) - 1):
	x = l1[i + 1] - l[i]
	mi = max(mi, x)
print(mi)


def int_fn():
	return int(input())

def str_fn():
	return input()

def int_list_fn():
	return [int(val) for val in input().split(' ')]

def solve(source: str, n: int, target: str, m: int):
	(min_list, max_list) = ([-1] * m, [-1] * m)
	i = 0
	for (idx, ch) in enumerate(source):
		if target[i] == ch:
			min_list[i] = idx
			i += 1
		if i == m:
			break
	i = m - 1
	for last_idx in range(n - 1, -1, -1):
		ch = source[last_idx]
		if ch == target[i]:
			max_list[i] = last_idx
			i -= 1
		if i < 0:
			break
	max_diff = 1
	for idx in range(1, m):
		max_diff = max(max_diff, max_list[idx] - min_list[idx - 1])
	print(max_diff)
	return
(n, m) = int_list_fn()
source = str_fn()
target = str_fn()
solve(source, n, target, m)
pass


import sys, functools, collections, bisect, math, heapq
input = sys.stdin.readline
sys.setrecursionlimit(100000)
for _ in range(1):
	(n, m) = map(int, input().strip().split())
	left = []
	right = collections.deque()
	s = input().strip()
	t = input().strip()
	j = 0
	for i in range(n):
		if s[i] == t[j]:
			left.append(i)
			j += 1
			if j == m:
				break
	j = m - 1
	for i in range(n - 1, -1, -1):
		if s[i] == t[j]:
			right.appendleft(i)
			j -= 1
			if j == -1:
				break
	ans = 0
	for i in range(m - 1):
		ans = max(ans, right[i + 1] - left[i])
	print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
(min_ind, max_ind) = ([-1] * m, [-1] * m)
index = 0
for i in range(n):
	if index < m and s[i] == t[index]:
		min_ind[index] = i
		index += 1
index = m - 1
for i in range(n - 1, -1, -1):
	if index >= 0 and s[i] == t[index]:
		max_ind[index] = i
		index -= 1
print(max((max_ind[i] - min_ind[i - 1] for i in range(1, m))))


import sys
import math
from itertools import permutations
from bisect import bisect_left
import heapq

def II():
	return int(sys.stdin.readline())

def LI():
	return list(map(int, sys.stdin.readline().split()))

def MI():
	return map(int, sys.stdin.readline().split())

def SI():
	return sys.stdin.readline().strip()

def FACT(n, mod):
	s = 1
	facts = [1]
	for i in range(1, n + 1):
		s *= i
		s %= mod
		facts.append(s)
	return facts[n]

def C(n, k, mod):
	return FACT(n, mod) * pow(FACT(k, mod) * FACT(n - k, mod) % mod, mod - 2, mod) % mod
(n, m) = MI()
s = list(SI())
t = list(SI())
d = [0 for i in range(m)]
d2 = [0 for i in range(m)]
l = 0
for i in range(n):
	if s[i] == t[l]:
		d[l] = i
		l += 1
	if l == m:
		break
r = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[r]:
		d2[r] = i
		r -= 1
	if r == -1:
		break
ma = 0
for i in range(1, m):
	ma = max(ma, d2[i] - d[i - 1])
print(ma)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
s = list(input())
t = list(input())
ans = 0
lefts = []
rights = []
j = 0
for i in range(n):
	if s[i] == t[j]:
		lefts.append(i)
		j += 1
j = m - 1
for i in range(n - 1, -1, -1):
	if s[i] == t[j]:
		rights.append(i)
		j -= 1
rights = rights[::-1]
for i in range(1, m):
	ans = max(ans, rights[i] - lefts[i - 1])
print(ans)


(n, m) = map(int, input().split())
s = input()
t = input()
a = []
ans = 0
i = -1
for x in t[:-1]:
	i = s.find(x, i + 1)
	a += [i]
i = n
for x in t[:0:-1]:
	i = s.rfind(x, 0, i)
	ans = max(ans, i - a.pop())
print(ans)


from collections import defaultdict
(n, m) = list(map(int, input().split()))
s = input()
t = input()
dic = defaultdict(list)
for (idx, ch) in enumerate(s):
	dic[ch].append(idx)
res = 0
small = []
big = []
dic_idx = {k: 0 for k in dic.keys()}
prev = None
for ch in t:
	while prev is not None and dic[ch][dic_idx[ch]] < prev:
		dic_idx[ch] += 1
	small.append(dic[ch][dic_idx[ch]])
	prev = dic[ch][dic_idx[ch]]
	dic_idx[ch] += 1
dic_idx = {k: -1 for k in dic.keys()}
prev = None
for ch in t[::-1]:
	while prev is not None and dic[ch][dic_idx[ch]] > prev:
		dic_idx[ch] -= 1
	big.append(dic[ch][dic_idx[ch]])
	prev = dic[ch][dic_idx[ch]]
	dic_idx[ch] -= 1
big = big[::-1]
for idx in range(len(t) - 1):
	res = max(res, big[idx + 1] - small[idx])
print(res)


from bisect import bisect_left, bisect_right

class Result:

	def __init__(self, index, value):
		self.index = index
		self.value = value

class BinarySearch:

	def __init__(self):
		pass

	@staticmethod
	def greater_than(num: int, func, size: int=1):
		if isinstance(func, list):
			index = bisect_right(func, num)
			if index == len(func):
				return Result(None, None)
			else:
				return Result(index, func[index])
		else:
			(alpha, omega) = (0, size - 1)
			if func(omega) <= num:
				return Result(None, None)
			while alpha < omega:
				if func(alpha) > num:
					return Result(alpha, func(alpha))
				if omega == alpha + 1:
					return Result(omega, func(omega))
				mid = (alpha + omega) // 2
				if func(mid) > num:
					omega = mid
				else:
					alpha = mid

	@staticmethod
	def less_than(num: int, func, size: int=1):
		if isinstance(func, list):
			index = bisect_left(func, num) - 1
			if index == -1:
				return Result(None, None)
			else:
				return Result(index, func[index])
		else:
			(alpha, omega) = (0, size - 1)
			if func(alpha) >= num:
				return Result(None, None)
			while alpha < omega:
				if func(omega) < num:
					return Result(omega, func(omega))
				if omega == alpha + 1:
					return Result(alpha, func(alpha))
				mid = (alpha + omega) // 2
				if func(mid) < num:
					alpha = mid
				else:
					omega = mid
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import gcd, ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y
bs = BinarySearch()
for _ in range(int(input()) if not True else 1):
	(n, k) = map(int, input().split())
	s = [ord(x) - 97 for x in input()]
	t = [ord(x) - 97 for x in input()]
	ans = 0
	index = [[] for i in range(26)]
	for i in range(len(s)):
		index[s[i]] += [i]
	cur = n - 1
	last_ind = [0] * k
	for i in range(k - 1, -1, -1):
		last_ind[i] = bs.less_than(cur + 1, index[t[i]]).value
		cur = last_ind[i] - 1
	cur = 0
	for i in range(k):
		least = bs.greater_than(cur - 1, index[t[i]]).value
		greatest = bs.less_than(last_ind[i] + 1, index[t[i]]).value
		if i:
			ans = max(ans, greatest - cur + 1)
		cur = least + 1
	print(ans)


(bl, sl) = map(int, input().split())
(b, s) = (input(), input())
c = 0
(i, cind) = (0, 0)
st = []
en = []
while 1:
	if b[cind] == s[i]:
		st.append(cind)
		i += 1
		if i == sl:
			break
	cind += 1
(i, cind) = (0, 0)
while 2:
	if b[bl - cind - 1] == s[sl - i - 1]:
		en.append(bl - cind - 1)
		i += 1
		if i == sl:
			break
	cind += 1
en = en[::-1]
for i in range(len(st) - 1):
	c = max(c, en[i + 1] - st[i])
print(max(c, en[-1] - st[-1]))


from collections import defaultdict as dd
(n, m) = map(int, input().split())
s = input()
t = input()
md = {}
mmd = {}
md[-1] = 0
mmd[m] = n - 1
for j in range(m):
	i = md[j - 1]
	if j > 0 and t[j] == t[j - 1]:
		i += 1
	while s[i] != t[j]:
		i += 1
	md[j] = i
for j in range(m - 1, -1, -1):
	i = mmd[j + 1]
	if j != m - 1 and t[j + 1] == t[j]:
		i -= 1
	while s[i] != t[j]:
		i -= 1
	mmd[j] = i
ans = 0
for j in range(1, m):
	ans = max(mmd[j] - md[j - 1], ans)
print(ans)


(N, M) = map(int, input().split())
S = input()
T = input()
A = []
B = []
si = 0
for t in T:
	while S[si] != t:
		si += 1
	A.append(si)
	si += 1
si = N - 1
for t in T[::-1]:
	while S[si] != t:
		si -= 1
	B.append(si)
	si -= 1
B.reverse()
ans = 0
for (a, b) in zip(A, B[1:]):
	ans = max(ans, b - a)
print(ans)


import sys
sys.setrecursionlimit(10 ** 6)

def lcm(a, b, curr, mx):
	if len(b) == 0:
		return max(mx, curr)
	if len(a) == 0:
		return 0
	v = 0
	if a[0] == b[0]:
		v = lcm(a[1:], b[1:], 0, max(curr, mx))
	return max(v, lcm(a[1:], b, curr + 1, mx))
(n, m) = list(map(int, input().split()))
s = input()
t = input()
(a, b) = ([], [])
l = 0
for i in range(m):
	while s[l] != t[i]:
		l += 1
	a.append(l)
	l += 1
l = n - 1
for i in range(m)[::-1]:
	while s[l] != t[i]:
		l -= 1
	b.append(l)
	l -= 1
b = b[::-1]
x = 0
for i in range(len(a) - 1):
	x = max(x, b[i + 1] - a[i])
print(x)


(n, m) = map(int, input().split())
s = str(input())
t = str(input())
pref = [-1] * m
idx = 0
for i in range(n):
	if t[idx] == s[i]:
		pref[idx] = i
		idx += 1
		if idx == m:
			break
suff = [-1] * m
idx = m - 1
for i in range(n - 1, -1, -1):
	if t[idx] == s[i]:
		suff[idx] = i
		idx -= 1
		if idx < 0:
			break
ans = 0
for i in range(0, m - 1):
	ans = max(ans, suff[i + 1] - pref[i])
print(ans)