← Home
package main

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

type Bucket struct {
	idxs []int
}

type Frame struct {
	name string
	adv  []int
}

func main() {
	data, _ := io.ReadAll(os.Stdin)
	text := string(data)
	text = strings.ReplaceAll(text, "\r", "")
	lines := strings.Split(strings.TrimRight(text, "\n"), "\n")
	if len(lines) < 2 {
		return
	}
	doc := lines[0]
	m, _ := strconv.Atoi(strings.TrimSpace(lines[1]))
	queries := make([][]string, m)
	for i := 0; i < m; i++ {
		if 2+i < len(lines) {
			queries[i] = strings.Fields(strings.TrimSpace(lines[2+i]))
		} else {
			queries[i] = []string{}
		}
	}

	// Prepare buckets for all query tokens
	buckets := make(map[string]*Bucket)
	for _, q := range queries {
		for _, w := range q {
			if _, ok := buckets[w]; !ok {
				buckets[w] = &Bucket{}
			}
		}
	}

	lens := make([]int, m)
	for i := 0; i < m; i++ {
		lens[i] = len(queries[i])
	}

	ans := make([]int, m)
	k := make([]int, m)         // matched prefix length
	pos := make([]int, m)       // position in current bucket
	curKey := make([]string, m) // current bucket key for query
	for i := 0; i < m; i++ {
		pos[i] = -1
		if lens[i] > 0 {
			key := queries[i][0]
			b := buckets[key]
			b.idxs = append(b.idxs, i)
			pos[i] = len(b.idxs) - 1
			curKey[i] = key
		}
	}

	var stack []Frame
	var pop func()

	// Helper: push a node
	push := func(name string, selfClosing bool) {
		var advancers []int
		if b, ok := buckets[name]; ok {
			if len(b.idxs) > 0 {
				advancers = b.idxs
				b.idxs = nil // detach to avoid aliasing
			}
		}
		// Detach all from their old bucket (they are advancing now)
		for _, j := range advancers {
			pos[j] = -1
			curKey[j] = ""
		}
		// Advance all
		for _, j := range advancers {
			k[j]++
			if k[j] == lens[j] {
				ans[j]++
			} else {
				next := queries[j][k[j]]
				nb := buckets[next]
				nb.idxs = append(nb.idxs, j)
				pos[j] = len(nb.idxs) - 1
				curKey[j] = next
			}
		}
		stack = append(stack, Frame{name: name, adv: advancers})
		if selfClosing {
			// immediate pop
			pop()
		}
	}

	// Helper: pop a node
	pop = func() {
		if len(stack) == 0 {
			return
		}
		fr := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		for _, j := range fr.adv {
			// Remove from current bucket if present
			if k[j] < lens[j] {
				currKey := queries[j][k[j]]
				b := buckets[currKey]
				p := pos[j]
				if p >= 0 {
					last := b.idxs[len(b.idxs)-1]
					b.idxs[p] = last
					pos[last] = p
					b.idxs = b.idxs[:len(b.idxs)-1]
				}
				pos[j] = -1
				curKey[j] = ""
			}
			// Revert advancement at this frame
			k[j]--
			prevNext := queries[j][k[j]]
			b2 := buckets[prevNext]
			b2.idxs = append(b2.idxs, j)
			pos[j] = len(b2.idxs) - 1
			curKey[j] = prevNext
		}
	}

	// Parse document
	n := len(doc)
	for i := 0; i < n; {
		if doc[i] != '<' {
			i++
			continue
		}
		i++ // skip '<'
		if i < n && doc[i] == '/' {
			// closing
			i++
			for i < n && doc[i] != '>' {
				i++
			}
			if i < n && doc[i] == '>' {
				i++
			}
			pop()
		} else {
			// opening or self-closing
			start := i
			for i < n {
				c := doc[i]
				if c == '/' || c == '>' {
					break
				}
				i++
			}
			name := doc[start:i]
			if i < n && doc[i] == '/' {
				// self-closing
				i++
				if i < n && doc[i] == '>' {
					i++
				}
				push(name, true)
			} else {
				// opening
				if i < n && doc[i] == '>' {
					i++
				}
				push(name, false)
			}
		}
	}

	w := bufio.NewWriter(os.Stdout)
	for i := 0; i < m; i++ {
		fmt.Fprintln(w, ans[i])
	}
	w.Flush()
}