← Home
package main

import (
	"bufio"
	"os"
	"strconv"
)

const M1 = 1000000007
const M2 = 1000000009
const B1 = 313
const B2 = 317

var pow1 []uint32
var pow2 []uint32

func init() {
	pow1 = make([]uint32, 5000005)
	pow2 = make([]uint32, 5000005)
	pow1[0] = 1
	pow2[0] = 1
	for i := 1; i <= 5000000; i++ {
		pow1[i] = uint32((uint64(pow1[i-1]) * B1) % M1)
		pow2[i] = uint32((uint64(pow2[i-1]) * B2) % M2)
	}
}

func extGCD(a, b int) (int, int, int) {
	if b == 0 {
		return a, 1, 0
	}
	d1, x1, y1 := extGCD(b, a%b)
	return d1, y1, x1 - y1*(a/b)
}

func can_form(m, a, b int) bool {
	d, x, y := extGCD(a, b)
	if m%d != 0 {
		return false
	}
	u0 := x * (m / d)
	v0 := y * (m / d)
	stepU := b / d
	stepV := a / d

	var minK, maxK int
	if u0 >= 0 {
		minK = -(u0 / stepU)
	} else {
		minK = (-u0 + stepU - 1) / stepU
	}

	if v0 >= 0 {
		maxK = v0 / stepV
	} else {
		maxK = -(-v0 + stepV - 1) / stepV
	}

	return minK <= maxK
}

func solve() {
	scanner := bufio.NewScanner(os.Stdin)
	buf := make([]byte, 1024*1024*10)
	scanner.Buffer(buf, 1024*1024*20)
	scanner.Split(bufio.ScanWords)

	if !scanner.Scan() {
		return
	}
	T, _ := strconv.Atoi(scanner.Text())

	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	for t_case := 0; t_case < T; t_case++ {
		scanner.Scan()
		n, _ := strconv.Atoi(scanner.Text())

		scanner.Scan()
		m, _ := strconv.Atoi(scanner.Text())

		scanner.Scan()
		s := scanner.Text()

		scanner.Scan()
		t := scanner.Text()

		hashS1 := make([]uint32, n+1)
		hashS2 := make([]uint32, n+1)
		for i := 0; i < n; i++ {
			hashS1[i+1] = uint32((uint64(hashS1[i])*B1 + uint64(s[i])) % M1)
			hashS2[i+1] = uint32((uint64(hashS2[i])*B2 + uint64(s[i])) % M2)
		}

		hashT1 := make([]uint32, m+1)
		hashT2 := make([]uint32, m+1)
		for i := 0; i < m; i++ {
			hashT1[i+1] = uint32((uint64(hashT1[i])*B1 + uint64(t[i])) % M1)
			hashT2[i+1] = uint32((uint64(hashT2[i])*B2 + uint64(t[i])) % M2)
		}

		getHashS := func(l, r int) uint64 {
			length := r - l
			h1 := (uint64(hashS1[r]) + M1 - (uint64(hashS1[l])*uint64(pow1[length]))%M1) % M1
			h2 := (uint64(hashS2[r]) + M2 - (uint64(hashS2[l])*uint64(pow2[length]))%M2) % M2
			return (h1 << 32) | h2
		}

		getHashT := func(l, r int) uint64 {
			length := r - l
			h1 := (uint64(hashT1[r]) + M1 - (uint64(hashT1[l])*uint64(pow1[length]))%M1) % M1
			h2 := (uint64(hashT2[r]) + M2 - (uint64(hashT2[l])*uint64(pow2[length]))%M2) % M2
			return (h1 << 32) | h2
		}

		commutes := func(i int) bool {
			return getHashS(0, n-i) == getHashS(i, n) && getHashS(n-i, n) == getHashS(0, i)
		}

		isPrefix := true
		for j := 0; j < m; j++ {
			if t[j] != s[j%n] {
				isPrefix = false
				break
			}
		}

		ans := make([]byte, n-1)

		for i := 1; i < n; i++ {
			a := i
			b := n - i
			if commutes(i) {
				if isPrefix && can_form(m, a, b) {
					ans[i-1] = '1'
				} else {
					ans[i-1] = '0'
				}
			} else {
				var L, S, startL, startS int
				if a >= b {
					L, S = a, b
					startL, startS = 0, a
				} else {
					L, S = b, a
					startL, startS = a, 0
				}

				hashL := getHashS(startL, startL+L)
				hashSStr := getHashS(startS, startS+S)

				j := 0
				possible := true
				for j < m {
					if j+L <= m && getHashT(j, j+L) == hashL {
						j += L
					} else if j+S <= m && getHashT(j, j+S) == hashSStr {
						j += S
					} else {
						possible = false
						break
					}
				}
				if possible {
					ans[i-1] = '1'
				} else {
					ans[i-1] = '0'
				}
			}
		}
		out.WriteString(string(ans) + "\n")
	}
}

func main() {
	solve()
}