← Home
package main

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

type FastScanner struct {
	data []byte
	idx  int
}

func NewFastScanner() *FastScanner {
	data, _ := io.ReadAll(os.Stdin)
	return &FastScanner{data: data}
}

func (fs *FastScanner) Next() string {
	n := len(fs.data)
	for fs.idx < n && fs.data[fs.idx] <= ' ' {
		fs.idx++
	}
	start := fs.idx
	for fs.idx < n && fs.data[fs.idx] > ' ' {
		fs.idx++
	}
	return string(fs.data[start:fs.idx])
}

func (fs *FastScanner) NextInt() int {
	n := len(fs.data)
	for fs.idx < n && fs.data[fs.idx] <= ' ' {
		fs.idx++
	}
	sign := 1
	if fs.data[fs.idx] == '-' {
		sign = -1
		fs.idx++
	}
	val := 0
	for fs.idx < n && fs.data[fs.idx] > ' ' {
		val = val*10 + int(fs.data[fs.idx]-'0')
		fs.idx++
	}
	return val * sign
}

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

func buildSA(s []int) ([]int, []int) {
	n := len(s)
	sa := make([]int, n)
	x := make([]int, n)
	y := make([]int, n)
	m := 0
	for i, v := range s {
		x[i] = v
		if v > m {
			m = v
		}
	}
	c := make([]int, max(n, m)+1)

	for i := 0; i <= m; i++ {
		c[i] = 0
	}
	for i := 0; i < n; i++ {
		c[x[i]]++
	}
	for i := 1; i <= m; i++ {
		c[i] += c[i-1]
	}
	for i := n - 1; i >= 0; i-- {
		v := x[i]
		c[v]--
		sa[c[v]] = i
	}

	for k, p := 1, 0; ; k <<= 1 {
		p = 0
		if k < n {
			for i := n - k; i < n; i++ {
				y[p] = i
				p++
			}
			for i := 0; i < n; i++ {
				if sa[i] >= k {
					y[p] = sa[i] - k
					p++
				}
			}
		} else {
			for i := 0; i < n; i++ {
				y[p] = i
				p++
			}
		}

		for i := 0; i <= m; i++ {
			c[i] = 0
		}
		for i := 0; i < n; i++ {
			c[x[y[i]]]++
		}
		for i := 1; i <= m; i++ {
			c[i] += c[i-1]
		}
		for i := n - 1; i >= 0; i-- {
			v := x[y[i]]
			c[v]--
			sa[c[v]] = y[i]
		}

		x, y = y, x
		p = 1
		x[sa[0]] = 1
		for i := 1; i < n; i++ {
			a := sa[i]
			b := sa[i-1]
			a1 := y[a]
			b1 := y[b]
			a2 := 0
			b2 := 0
			if a+k < n {
				a2 = y[a+k]
			}
			if b+k < n {
				b2 = y[b+k]
			}
			if a1 == b1 && a2 == b2 {
				x[a] = p
			} else {
				p++
				x[a] = p
			}
		}
		if p == n {
			break
		}
		m = p
	}

	rank := make([]int, n)
	for i := 0; i < n; i++ {
		rank[sa[i]] = i
	}
	lcp := make([]int, n)
	h := 0
	for i := 0; i < n; i++ {
		r := rank[i]
		if r == 0 {
			continue
		}
		j := sa[r-1]
		for i+h < n && j+h < n && s[i+h] == s[j+h] {
			h++
		}
		lcp[r] = h
		if h > 0 {
			h--
		}
	}

	return sa, lcp
}

type Node struct {
	depth int32
	valid int32
	cnt   [11]int32
}

func finalize(child Node, parentDepth int32, parentCnt *[11]int32, rules int, L, R []int32) int64 {
	var res int64
	if child.cnt[0] > 0 && child.valid > parentDepth {
		ok := true
		for i := 1; i <= rules; i++ {
			v := child.cnt[i]
			if v < L[i] || v > R[i] {
				ok = false
				break
			}
		}
		if ok {
			res = int64(child.valid - parentDepth)
		}
	}
	for i := 0; i < 11; i++ {
		(*parentCnt)[i] += child.cnt[i]
	}
	return res
}

func main() {
	fs := NewFastScanner()

	mainS := fs.Next()
	rules := fs.NextInt()

	strs := make([]string, rules+1)
	strs[0] = mainS
	L := make([]int32, rules+1)
	R := make([]int32, rules+1)

	for i := 1; i <= rules; i++ {
		strs[i] = fs.Next()
		L[i] = int32(fs.NextInt())
		R[i] = int32(fs.NextInt())
	}

	totalAll := 0
	totalValid := 0
	for i := 0; i <= rules; i++ {
		totalAll += len(strs[i]) + 1
		totalValid += len(strs[i])
	}

	concat := make([]int, totalAll)
	rem := make([]int32, totalAll)
	grp := make([]byte, totalAll)

	pos := 0
	for g := 0; g <= rules; g++ {
		str := strs[g]
		m := len(str)
		for i := 0; i < m; i++ {
			concat[pos] = int(str[i]-'a') + 1
			rem[pos] = int32(m - i)
			grp[pos] = byte(g)
			pos++
		}
		concat[pos] = 27 + g
		pos++
	}

	sa, lcp := buildSA(concat)

	stack := make([]Node, 1, totalValid+2)
	var ans int64

	for i := 0; i < totalValid; i++ {
		var l int32
		if i > 0 {
			l = int32(lcp[i])
		}

		var last Node
		hasLast := false

		for stack[len(stack)-1].depth > l {
			node := stack[len(stack)-1]
			stack = stack[:len(stack)-1]
			if hasLast {
				ans += finalize(last, node.depth, &node.cnt, rules, L, R)
			}
			last = node
			hasLast = true
		}

		if stack[len(stack)-1].depth < l {
			x := Node{depth: l, valid: l}
			if hasLast {
				ans += finalize(last, x.depth, &x.cnt, rules, L, R)
			}
			stack = append(stack, x)
		} else if hasLast {
			top := len(stack) - 1
			ans += finalize(last, stack[top].depth, &stack[top].cnt, rules, L, R)
		}

		p := sa[i]
		rv := rem[p]
		leaf := Node{depth: rv + 1, valid: rv}
		leaf.cnt[int(grp[p])] = 1
		stack = append(stack, leaf)
	}

	var last Node
	hasLast := false
	for len(stack) > 1 {
		node := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		if hasLast {
			ans += finalize(last, node.depth, &node.cnt, rules, L, R)
		}
		last = node
		hasLast = true
	}
	if hasLast {
		ans += finalize(last, 0, &stack[0].cnt, rules, L, R)
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	fmt.Fprintln(out, ans)
	out.Flush()
}