← Home
```go
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	buf, _ := io.ReadAll(os.Stdin)
	pos := 0

	nextWord := func() string {
		for pos < len(buf) && buf[pos] <= ' ' {
			pos++
		}
		if pos >= len(buf) {
			return ""
		}
		start := pos
		for pos < len(buf) && buf[pos] > ' ' {
			pos++
		}
		return string(buf[start:pos])
	}

	nextInt := func() int {
		for pos < len(buf) && buf[pos] <= ' ' {
			pos++
		}
		if pos >= len(buf) {
			return 0
		}
		res := 0
		for pos < len(buf) && buf[pos] > ' ' {
			res = res*10 + int(buf[pos]-'0')
			pos++
		}
		return res
	}

	n := nextInt()
	m := nextInt()

	if n == 0 || m == 0 {
		return
	}

	max_states := 300005
	children := make([][26]int32, max_states)
	victims_at := make([][]int, max_states)

	sz := 1

	for i := 1; i <= n; i++ {
		s := nextWord()
		curr := 0
		for j := 0; j < len(s); j++ {
			c := s[j] - 'a'
			if children[curr][c] == 0 {
				children[curr][c] = int32(sz)
				sz++
			}
			curr = int(children[curr][c])
		}
		victims_at[curr] = append(victims_at[curr], i)
	}

	fail := make([]int, sz)
	queue := make([]int, 0, sz)

	for i := 0; i < 26; i++ {
		if children[0][i] != 0 {
			fail[children[0][i]] = 0
			queue = append(queue, int(children[0][i]))
		}
	}

	for len(queue) > 0 {
		u := queue[0]
		queue = queue[1:]
		for i := 0; i < 26; i++ {
			v := int(children[u][i])
			if v != 0 {
				fail[v] = int(children[fail[u]][i])
				queue = append(queue, v)
			} else {
				children[u][i] = children[fail[u]][i]
			}
		}
	}

	fail_tree := make([][]int, sz)
	for i := 1; i < sz; i++ {
		fail_tree[fail[i]] = append(fail_tree[fail[i]], i)
	}

	size := make([]int, sz)
	heavy := make([]int, sz)
	for i := range heavy {
		heavy[i] = -1
	}
	head := make([]int, sz)
	dfn := make([]int, sz)
	dfn_to_node := make([]int, sz)
	timer := 0

	var dfs1 func(u int)
	dfs1 = func(u int) {
		size[u] = 1
		max_sub := 0
		for _, v := range fail_tree[u] {
			dfs1(v)
			size[u] += size[v]
			if size[v] > max_sub {
				max_sub = size[v]
				heavy[u] = v
			}
		}
	}

	var dfs2 func(u, h int)
	dfs2 = func(u, h int) {
		head[u] = h
		dfn[u] = timer
		dfn_to_node[timer] = u
		timer++
		if heavy[u] != -1 {
			dfs2(heavy[u], h)
		}
		for _, v := range fail_tree[u] {
			if v != heavy[u] {
				dfs2(v, v)
			}
		}
	}

	dfs1(0)
	dfs2(0, 0)

	start_vic := make([]int, sz)
	end_vic := make([]int, sz)
	pos_in_segtree := make([]int, n+1)
	seg_timer := 0

	for i := 0; i < sz; i++ {
		u := dfn_to_node[i]
		start_vic[u] = seg_timer
		for _, vic_id := range victims_at[u] {
			pos_in_segtree[vic_id] = seg_timer
			seg_timer++
		}
		end_vic[u] = seg_timer - 1
	}

	tree := make([]int, 4*n+4)

	var update_seg func(node, start, end, idx, val int)
	update_seg = func(node, start, end, idx, val int) {
		if start == end {
			tree[node] = val
			return
		}
		mid := (start + end) / 2
		if idx <= mid {
			update_seg(2*node, start, mid, idx, val)
		} else {
			update_seg(2*node+1, mid+1, end, idx, val)
		}
		tree[node] = max(tree[2*node], tree[2*node+1])
	}

	var query_seg func(node, start, end, l, r int) int
	query_seg = func(node, start, end, l, r int) int {
		if r < start || end < l {
			return -1
		}
		if l <= start && end <= r {
			return tree[node]
		}
		mid := (start + end) / 2
		res := -1
		if l <= mid {
			res = max(res, query_seg(2*node, start, mid, l, r))
		}
		if r > mid {
			res = max(res, query_seg(2*node+1, mid+1, end, l, r))
		}
		return res
	}

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

	last_query := make([]int, sz)
	query_id := 0

	for i := 0; i < m; i++ {
		type_q := nextInt()
		if type_q == 1 {
			idx := nextInt()
			x := nextInt()
			update_seg(1, 0, n-1, pos_in_segtree[idx], x)
		} else {
			q := nextWord()
			query_id++
			ans := -1
			curr := 0
			for j := 0; j < len(q); j++ {
				curr = int(children[curr][q[j]-'a'])
				u := curr
				for u != 0 && last_query[u] != query_id {
					last_query[u] = query_id
					top := head[u]
					l := start_vic[top]
					r := end_vic[u]
					if l <= r {
						ans = max(ans, query_seg(1, 0, n-1, l, r))
					}
					u = fail[top]
				}
			}
			fmt.Fprintln(out, ans)
		}
	}
}
```