← Home
```go
package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"time"
)

// Suffix Automaton Node
type stNode struct {
	len, link int
	next      [2]int // 0 for 'O', 1 for 'X'
}

// Function to count distinct substrings using Suffix Automaton
func countDistinctFast(s string) int {
	// Initialize SAM
	// Pre-allocate to optimize performance
	st := make([]stNode, 1, 2*len(s)+1)
	st[0] = stNode{len: 0, link: -1, next: [2]int{-1, -1}}
	last := 0

	for i := 0; i < len(s); i++ {
		c := 0
		if s[i] == 'X' {
			c = 1
		}

		cur := len(st)
		st = append(st, stNode{len: st[last].len + 1, link: 0, next: [2]int{-1, -1}})
		p := last
		for p != -1 && st[p].next[c] == -1 {
			st[p].next[c] = cur
			p = st[p].link
		}
		if p == -1 {
			st[cur].link = 0
		} else {
			q := st[p].next[c]
			if st[p].len+1 == st[q].len {
				st[cur].link = q
			} else {
				clone := len(st)
				st = append(st, stNode{
					len:  st[p].len + 1,
					link: st[q].link,
					next: st[q].next,
				})
				for p != -1 && st[p].next[c] == q {
					st[p].next[c] = clone
					p = st[p].link
				}
				st[q].link = clone
				st[cur].link = clone
			}
		}
		last = cur
	}

	ans := 0
	for i := 1; i < len(st); i++ {
		ans += st[i].len - st[st[i].link].len
	}
	return ans
}

func main() {
	rand.Seed(time.Now().UnixNano())

	scanner := bufio.NewScanner(os.Stdin)
	// Set a large buffer to handle potentially long lines if necessary
	buf := make([]byte, 64*1024)
	scanner.Buffer(buf, 1024*1024)

	if !scanner.Scan() {
		return
	}
	var n int
	fmt.Sscanf(scanner.Text(), "%d", &n)

	words := make([]string, 0, n)
	// Map power -> indices [i, j]
	powerToIndices := make(map[int][2]int)
	// Set to keep track of used powers to ensure uniqueness
	usedPowers := make(map[int]bool)

	// Greedily generate n words
	for i := 0; i < n; i++ {
		for {
			// Generate random string of length 300-320
			l := 300 + rand.Intn(21)
			b := make([]byte, l)
			for k := 0; k < l; k++ {
				if rand.Intn(2) == 0 {
					b[k] = 'O'
				} else {
					b[k] = 'X'
				}
			}
			cand := string(b)

			valid := true
			// Temporary map to hold powers generated by this candidate combined with existing words
			currentBatch := make(map[int][2]int)

			// Check cand + cand
			pSelf := countDistinctFast(cand + cand)
			if usedPowers[pSelf] {
				valid = false
			} else {
				currentBatch[pSelf] = [2]int{i + 1, i + 1}
			}

			if valid {
				for j, w := range words {
					// Check cand + words[j]
					p1 := countDistinctFast(cand + w)
					if usedPowers[p1] {
						valid = false; break
					}
					if _, exists := currentBatch[p1]; exists {
						valid = false; break
					}
					currentBatch[p1] = [2]int{i + 1, j + 1}

					// Check words[j] + cand
					p2 := countDistinctFast(w + cand)
					if usedPowers[p2] {
						valid = false; break
					}
					if _, exists := currentBatch[p2]; exists {
						valid = false; break
					}
					currentBatch[p2] = [2]int{j + 1, i + 1}
				}
			}

			if valid {
				words = append(words, cand)
				for p, idx := range currentBatch {
					usedPowers[p] = true
					powerToIndices[p] = idx
				}
				break
			}
		}
	}

	// Output the generated words
	for i, w := range words {
		if i > 0 {
			fmt.Print(" ")
		}
		fmt.Print(w)
	}
	fmt.Println()

	// Process requests
	for scanner.Scan() {
		text := scanner.Text()
		var p int
		_, err := fmt.Sscanf(text, "%d", &p)
		if err != nil {
			break
		}
		if idx, ok := powerToIndices[p]; ok {
			fmt.Printf("%d %d\n", idx[0], idx[1])
		}
	}
}
```