#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <climits>
#include <iomanip>
#include <iostream>
#include <map>
#include <unordered_map>
#include <queue>
#include <deque>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <stack>
#include <list>
#include <bitset>
#include <cassert>
#define clr(x) memset((x), 0, sizeof(x))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define mp make_pair
#define For(i, st, en) for(int i=(st); i<=(int)(en); i++)
#define Ford(i, st, en) for(int i=(st); i>=(int)(en); i--)
#define forn(i, n) for(int i=0; i<(int)(n); i++)
#define ford(i, n) for(int i=(n)-1; i>=0; i--)
#define fori(it, x) for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define in(x) int (x); input((x));
#define x first
#define y second
#define less(a,b) ((a) < (b) - EPS)
#define more(a,b) ((a) > (b) + EPS)
#define eq(a,b) (fabs((a) - (b)) < EPS)
#define remax(a, b) ((a) = (b) > (a) ? (b) : (a))
#define remin(a, b) ((a) = (b) < (a) ? (b) : (a))
using namespace std; typedef long double ld; template <class _T> inline _T sqr(const _T& x) {return x * x;} template <class _T> inline string tostr(const _T& a) {ostringstream os(""); os << a; return os.str();} const ld PI = 3.1415926535897932384626433832795L; const ld EPS = 1e-12; char TEMPORARY_CHAR; typedef long long ll; typedef unsigned long long ull; typedef set < int > SI; typedef vector < int > VI; typedef vector < vector < int > > VVI; typedef map < string, int > MSI; typedef pair < int, int > PII; const int INF = 1e9; typedef complex<ld> cbase; inline void fft (vector<cbase> &a, bool invert) {int n = (int)a.size(); for (int i = 1, j = 0; i < n; ++i) {int bit = n >> 1; for (; j >= bit; bit >>= 1) j -= bit; j += bit; if (i < j) swap(a[i], a[j]);} for (int len = 2; len <= n; len <<= 1) {ld ang = 2 * PI / len * (invert ? -1 : 1); cbase wlen(cos(ang), sin(ang)); for (int i = 0; i < n; i += len) {cbase w(1); for (int j=0; j < len / 2; ++j) {cbase u = a[i + j], v = a[i + j + len / 2] * w; a[i + j] = u + v; a[i + j + len / 2] = u - v; w *= wlen;}}} if (invert) for (int i = 0; i < n; ++i) a[i] /= n;} inline void input(int &a) {a = 0; while (((TEMPORARY_CHAR = getchar()) > '9' || TEMPORARY_CHAR < '0') && (TEMPORARY_CHAR != '-')){} char neg = 0; if (TEMPORARY_CHAR == '-') {neg = 1; TEMPORARY_CHAR = getchar();} while (TEMPORARY_CHAR <= '9' && TEMPORARY_CHAR >= '0') {a = (a << 3) + (a << 1) + TEMPORARY_CHAR - '0'; TEMPORARY_CHAR = getchar();} if (neg) a = -a;} inline void out(ll a) {if (!a) putchar('0'); if (a < 0) {putchar('-'); a = -a;} char s[20]; int i; for(i = 0; a; ++i) {s[i] = '0' + a % 10; a /= 10;} ford(j, i) putchar(s[j]);} inline int nxt() {in(ret); return ret;} struct lnum {vector <int> a; int base; lnum(int num = 0, int base = 1000000000):base(base) {if (!num) a.resize(1); while(num) {a.pb(num % base); num /= base;}} inline int len() const {return a.size();} lnum & operator=(const lnum &l) {if (this != &l) {a = l.a; base = l.base;} return *this;} inline friend lnum operator+(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; int ln = l.len(), rn = r.len(); int n = max(ln, rn); ret.a.resize(n); int o = 0; for(int i = 0; i < n; ++i) {int s = o; if (i < ln) s += l.a[i]; if (i < rn) s += r.a[i]; o = s >= base; if (o) s -= base; ret.a[i] = s;} if (o) ret.a.push_back(1); return ret;} inline friend lnum operator-(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; int n = l.len(); int rn = r.len(); ret.a.resize(n); int o = 0; for(int i = 0; i < n; ++i) {int s = l.a[i] - o; if (i < rn) s -= r.a[i]; o = s < 0; if (o) s += base; ret.a[i] = s;} if (ret.len() > 1 && !ret.a.back()) ret.a.pop_back(); return ret;} inline friend lnum operator*(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; if (l.len() * r.len() > 1000000) {vector<cbase> fa (l.a.begin(), l.a.end()), fb (r.a.begin(), r.a.end()); int n = 1; while (n < max (l.len(), r.len())) n <<= 1; n <<= 1; fa.resize (n), fb.resize (n); fft (fa, false), fft (fb, false); for (int i = 0; i < n; ++i) fa[i] *= fb[i]; fft (fa, true); ret.a.resize(n); for (int i = 0; i < n; ++i) ret.a[i] = int (fa[i].real() + 0.5); int carry = 0; for (int i=0; i < n; ++i) {ret.a[i] += carry; carry = ret.a[i] / base; ret.a[i] %= base;}} else {ret.a.resize(l.len() + r.len()); for (int i = 0; i < l.len(); ++i) for (int j = 0, carry = 0; j < r.len() || carry; ++j) {long long cur = ret.a[i + j] + (ll)l.a[i] * (j < r.len() ? r.a[j] : 0) + carry; ret.a[i + j] = cur % base; carry = cur / base;}} while (ret.len() > 1 && !ret.a.back()) ret.a.pop_back(); return ret;} inline friend lnum operator/(const lnum &l, const int &r) {lnum ret(0, l.base); ret.a.resize(l.len()); int carry = 0; for(int i = l.len() - 1; i >= 0; --i) {long long cur = l.a[i] + (ll)carry * l.base; ret.a[i] = cur / r; carry = cur % r;} while (ret.len() > 1 && ret.a.back() == 0) ret.a.pop_back(); return ret;}  inline friend bool operator<(const lnum &l, const lnum &r) {if (l.len() < r.len()) return true; if (l.len() > r.len()) return false; int n = l.len(); for(int i = n - 1; i >= 0; --i) {if (l.a[i] < r.a[i]) return true; if (l.a[i] > r.a[i]) return false;} return false;} inline friend bool operator>(const lnum &l, const lnum &r) {return r < l;} inline friend bool operator==(const lnum &l, const lnum &r) {if (l.len() != r.len()) return false; int n = l.len(); for(int i = n - 1; i; --i) {if (l.a[i] != r.a[i]) return false;} return true;} inline friend bool operator!=(const lnum &l, const lnum &r) {return !(l == r);} inline void print() {if (base == 1000000000) {printf("%d", a.back()); for(int i = a.size() - 2; i >=0; --i) printf("%09d", a[i]);} else {for(int i = a.size() - 1; i >= 0; --i) printf("%d", a[i]);}}};

const int k = 1501;

struct node
{
    node * next[26];
    node * link;
    int cnt[11];
    int len;
    node()
    {
        link = 0;
        memset(next, 0, sizeof(next));
        memset(cnt, 0, sizeof(cnt));
        len = 0;
    }
    node(node * x)
    {
        link = x->link;
        len = x->len;
        memset(cnt, 0, sizeof(cnt));
        memcpy(next, x->next, sizeof(next));
    }
};

node * last, * root;

vector <node *> nodes;

void add(int c)
{
    node * cur = new node();
    nodes.pb(cur);
    cur->len = last->len + 1;
    node * p = last;
    for(; p && !p->next[c]; p = p->link)
        p->next[c] = cur;
    if (!p)
    {
        cur->link = root;
    }
    else
    {
        node * q = p->next[c];
        if (p->len + 1 == q->len)
        {
            cur->link = q;
        }
        else
        {
            node * cl = new node(q);
            nodes.pb(cl);
            cl->len = p->len + 1;
            for(; p && p->next[c] == q; p = p->link)
                p->next[c] = cl;
            q->link = cur->link = cl;
        }
    }
    last = cur;
}

void process(const string & s, int ind)
{
    last = root;
    int len = 0;
    for(char c : s)
    {
        ++len;
        if (last->next[c - 'a'] && last->next[c - 'a']->len == len)
            last = last->next[c - 'a'];
        else
            add(c - 'a');
        ++last->cnt[ind];
    }
}

bool cmp(node * l, node * r)
{
    return l->len > r->len;
}

void init()
{
    last = root = new node();
}

string ok;

int main()
{
    init();
    int l[11], r[11];
    string s[11];
    cin >> s[0];
    l[0] = 1, r[0] = INF;
    int n;
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        cin >> s[i] >> l[i] >> r[i];
    }
    ++n;
    for(int i = 0; i < n; ++i)
        process(s[i], i);

    sort(all(nodes), cmp);

    ll ans = 0;

    for(node * cur : nodes)
    {
        bool ok = true;
        for(int j = 0; j < n; ++j)
        {
            cur->link->cnt[j] += cur->cnt[j];
            if (cur->cnt[j] < l[j] || cur->cnt[j] > r[j])
                ok = false;
        }
        if (ok)
            ans += cur->len - cur->link->len;
    }
    cout << ans << endl;
    return 0;
}


#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <climits>
#include <iomanip>
#include <iostream>
#include <map>
#include <unordered_map>
#include <queue>
#include <deque>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <stack>
#include <list>
#include <bitset>
#include <cassert>
#define clr(x) memset((x), 0, sizeof(x))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define mp make_pair
#define For(i, st, en) for(int i=(st); i<=(int)(en); i++)
#define Ford(i, st, en) for(int i=(st); i>=(int)(en); i--)
#define forn(i, n) for(int i=0; i<(int)(n); i++)
#define ford(i, n) for(int i=(n)-1; i>=0; i--)
#define fori(it, x) for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define in(x) int (x); input((x));
#define x first
#define y second
#define less(a,b) ((a) < (b) - EPS)
#define more(a,b) ((a) > (b) + EPS)
#define eq(a,b) (fabs((a) - (b)) < EPS)
#define remax(a, b) ((a) = (b) > (a) ? (b) : (a))
#define remin(a, b) ((a) = (b) < (a) ? (b) : (a))
using namespace std; typedef long double ld; template <class _T> inline _T sqr(const _T& x) {return x * x;} template <class _T> inline string tostr(const _T& a) {ostringstream os(""); os << a; return os.str();} const ld PI = 3.1415926535897932384626433832795L; const ld EPS = 1e-12; char TEMPORARY_CHAR; typedef long long ll; typedef unsigned long long ull; typedef set < int > SI; typedef vector < int > VI; typedef vector < vector < int > > VVI; typedef map < string, int > MSI; typedef pair < int, int > PII; const int INF = 1e9; typedef complex<ld> cbase; inline void fft (vector<cbase> &a, bool invert) {int n = (int)a.size(); for (int i = 1, j = 0; i < n; ++i) {int bit = n >> 1; for (; j >= bit; bit >>= 1) j -= bit; j += bit; if (i < j) swap(a[i], a[j]);} for (int len = 2; len <= n; len <<= 1) {ld ang = 2 * PI / len * (invert ? -1 : 1); cbase wlen(cos(ang), sin(ang)); for (int i = 0; i < n; i += len) {cbase w(1); for (int j=0; j < len / 2; ++j) {cbase u = a[i + j], v = a[i + j + len / 2] * w; a[i + j] = u + v; a[i + j + len / 2] = u - v; w *= wlen;}}} if (invert) for (int i = 0; i < n; ++i) a[i] /= n;} inline void input(int &a) {a = 0; while (((TEMPORARY_CHAR = getchar()) > '9' || TEMPORARY_CHAR < '0') && (TEMPORARY_CHAR != '-')){} char neg = 0; if (TEMPORARY_CHAR == '-') {neg = 1; TEMPORARY_CHAR = getchar();} while (TEMPORARY_CHAR <= '9' && TEMPORARY_CHAR >= '0') {a = (a << 3) + (a << 1) + TEMPORARY_CHAR - '0'; TEMPORARY_CHAR = getchar();} if (neg) a = -a;} inline void out(ll a) {if (!a) putchar('0'); if (a < 0) {putchar('-'); a = -a;} char s[20]; int i; for(i = 0; a; ++i) {s[i] = '0' + a % 10; a /= 10;} ford(j, i) putchar(s[j]);} inline int nxt() {in(ret); return ret;} struct lnum {vector <int> a; int base; lnum(int num = 0, int base = 1000000000):base(base) {if (!num) a.resize(1); while(num) {a.pb(num % base); num /= base;}} inline int len() const {return a.size();} lnum & operator=(const lnum &l) {if (this != &l) {a = l.a; base = l.base;} return *this;} inline friend lnum operator+(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; int ln = l.len(), rn = r.len(); int n = max(ln, rn); ret.a.resize(n); int o = 0; for(int i = 0; i < n; ++i) {int s = o; if (i < ln) s += l.a[i]; if (i < rn) s += r.a[i]; o = s >= base; if (o) s -= base; ret.a[i] = s;} if (o) ret.a.push_back(1); return ret;} inline friend lnum operator-(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; int n = l.len(); int rn = r.len(); ret.a.resize(n); int o = 0; for(int i = 0; i < n; ++i) {int s = l.a[i] - o; if (i < rn) s -= r.a[i]; o = s < 0; if (o) s += base; ret.a[i] = s;} if (ret.len() > 1 && !ret.a.back()) ret.a.pop_back(); return ret;} inline friend lnum operator*(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; if (l.len() * r.len() > 1000000) {vector<cbase> fa (l.a.begin(), l.a.end()), fb (r.a.begin(), r.a.end()); int n = 1; while (n < max (l.len(), r.len())) n <<= 1; n <<= 1; fa.resize (n), fb.resize (n); fft (fa, false), fft (fb, false); for (int i = 0; i < n; ++i) fa[i] *= fb[i]; fft (fa, true); ret.a.resize(n); for (int i = 0; i < n; ++i) ret.a[i] = int (fa[i].real() + 0.5); int carry = 0; for (int i=0; i < n; ++i) {ret.a[i] += carry; carry = ret.a[i] / base; ret.a[i] %= base;}} else {ret.a.resize(l.len() + r.len()); for (int i = 0; i < l.len(); ++i) for (int j = 0, carry = 0; j < r.len() || carry; ++j) {long long cur = ret.a[i + j] + (ll)l.a[i] * (j < r.len() ? r.a[j] : 0) + carry; ret.a[i + j] = cur % base; carry = cur / base;}} while (ret.len() > 1 && !ret.a.back()) ret.a.pop_back(); return ret;} inline friend lnum operator/(const lnum &l, const int &r) {lnum ret(0, l.base); ret.a.resize(l.len()); int carry = 0; for(int i = l.len() - 1; i >= 0; --i) {long long cur = l.a[i] + (ll)carry * l.base; ret.a[i] = cur / r; carry = cur % r;} while (ret.len() > 1 && ret.a.back() == 0) ret.a.pop_back(); return ret;}  inline friend bool operator<(const lnum &l, const lnum &r) {if (l.len() < r.len()) return true; if (l.len() > r.len()) return false; int n = l.len(); for(int i = n - 1; i >= 0; --i) {if (l.a[i] < r.a[i]) return true; if (l.a[i] > r.a[i]) return false;} return false;} inline friend bool operator>(const lnum &l, const lnum &r) {return r < l;} inline friend bool operator==(const lnum &l, const lnum &r) {if (l.len() != r.len()) return false; int n = l.len(); for(int i = n - 1; i; --i) {if (l.a[i] != r.a[i]) return false;} return true;} inline friend bool operator!=(const lnum &l, const lnum &r) {return !(l == r);} inline void print() {if (base == 1000000000) {printf("%d", a.back()); for(int i = a.size() - 2; i >=0; --i) printf("%09d", a[i]);} else {for(int i = a.size() - 1; i >= 0; --i) printf("%d", a[i]);}}};

const int k = 1501;

struct node
{
    node * next[26];
    node * link;
    int cnt[10];
    int len;
    node()
    {
        link = 0;
        memset(next, 0, sizeof(next));
        memset(cnt, 0, sizeof(cnt));
        len = 0;
    }
    node(node * x)
    {
        link = x->link;
        len = x->len;
        memset(cnt, 0, sizeof(cnt));
        memcpy(next, x->next, sizeof(next));
    }
};

node * last, * root;

vector <node *> nodes;

void add(int c)
{
    node * cur = new node();
    nodes.pb(cur);
    cur->len = last->len + 1;
    node * p = last;
    for(; p && !p->next[c]; p = p->link)
        p->next[c] = cur;
    if (!p)
    {
        cur->link = root;
    }
    else
    {
        node * q = p->next[c];
        if (p->len + 1 == q->len)
        {
            cur->link = q;
        }
        else
        {
            node * cl = new node(q);
            nodes.pb(cl);
            cl->len = p->len + 1;
            for(; p && p->next[c] == q; p = p->link)
                p->next[c] = cl;
            q->link = cur->link = cl;
        }
    }
    last = cur;
}

void process(const string & s, int ind)
{
    last = root;
    int len = 0;
    for(char c : s)
    {
        ++len;
        if (last->next[c - 'a'] && last->next[c - 'a']->len == len)
            last = last->next[c - 'a'];
        else
            add(c - 'a');
        ++last->cnt[ind];
    }
}

bool cmp(node * l, node * r)
{
    return l->len > r->len;
}

void init()
{
    last = root = new node();
}

string ok;

int main()
{
    string a;
    cin >> a;
    init();
    for(char c : a)
        add(c - 'a');
    int n;
    cin >> n;
    int l[n], r[n];
    string s[n];
    for(int i = 0; i < n; ++i)
    {
        cin >> s[i] >> l[i] >> r[i];
        process(s[i], i);
    }

    sort(all(nodes), cmp);

    ll ans = 0;

    for(node * cur : nodes)
    {
        bool ok = true;
        for(int j = 0; j < n; ++j)
        {
            cur->link->cnt[j] += cur->cnt[j];
            if (cur->cnt[j] < l[j] || cur->cnt[j] > r[j])
                ok = false;
        }
        if (ok && cur->link)
            ans += cur->len - cur->link->len;
    }
    cout << ans << endl;
    return 0;
}


#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <climits>
#include <iomanip>
#include <iostream>
#include <map>
#include <unordered_map>
#include <queue>
#include <deque>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <stack>
#include <list>
#include <bitset>
#include <cassert>
#define clr(x) memset((x), 0, sizeof(x))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define mp make_pair
#define For(i, st, en) for(int i=(st); i<=(int)(en); i++)
#define Ford(i, st, en) for(int i=(st); i>=(int)(en); i--)
#define forn(i, n) for(int i=0; i<(int)(n); i++)
#define ford(i, n) for(int i=(n)-1; i>=0; i--)
#define fori(it, x) for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define in(x) int (x); input((x));
#define x first
#define y second
#define less(a,b) ((a) < (b) - EPS)
#define more(a,b) ((a) > (b) + EPS)
#define eq(a,b) (fabs((a) - (b)) < EPS)
#define remax(a, b) ((a) = (b) > (a) ? (b) : (a))
#define remin(a, b) ((a) = (b) < (a) ? (b) : (a))
using namespace std; typedef long double ld; template <class _T> inline _T sqr(const _T& x) {return x * x;} template <class _T> inline string tostr(const _T& a) {ostringstream os(""); os << a; return os.str();} const ld PI = 3.1415926535897932384626433832795L; const ld EPS = 1e-12; char TEMPORARY_CHAR; typedef long long ll; typedef unsigned long long ull; typedef set < int > SI; typedef vector < int > VI; typedef vector < vector < int > > VVI; typedef map < string, int > MSI; typedef pair < int, int > PII; const int INF = 1e9; typedef complex<ld> cbase; inline void fft (vector<cbase> &a, bool invert) {int n = (int)a.size(); for (int i = 1, j = 0; i < n; ++i) {int bit = n >> 1; for (; j >= bit; bit >>= 1) j -= bit; j += bit; if (i < j) swap(a[i], a[j]);} for (int len = 2; len <= n; len <<= 1) {ld ang = 2 * PI / len * (invert ? -1 : 1); cbase wlen(cos(ang), sin(ang)); for (int i = 0; i < n; i += len) {cbase w(1); for (int j=0; j < len / 2; ++j) {cbase u = a[i + j], v = a[i + j + len / 2] * w; a[i + j] = u + v; a[i + j + len / 2] = u - v; w *= wlen;}}} if (invert) for (int i = 0; i < n; ++i) a[i] /= n;} inline void input(int &a) {a = 0; while (((TEMPORARY_CHAR = getchar()) > '9' || TEMPORARY_CHAR < '0') && (TEMPORARY_CHAR != '-')){} char neg = 0; if (TEMPORARY_CHAR == '-') {neg = 1; TEMPORARY_CHAR = getchar();} while (TEMPORARY_CHAR <= '9' && TEMPORARY_CHAR >= '0') {a = (a << 3) + (a << 1) + TEMPORARY_CHAR - '0'; TEMPORARY_CHAR = getchar();} if (neg) a = -a;} inline void out(ll a) {if (!a) putchar('0'); if (a < 0) {putchar('-'); a = -a;} char s[20]; int i; for(i = 0; a; ++i) {s[i] = '0' + a % 10; a /= 10;} ford(j, i) putchar(s[j]);} inline int nxt() {in(ret); return ret;} struct lnum {vector <int> a; int base; lnum(int num = 0, int base = 1000000000):base(base) {if (!num) a.resize(1); while(num) {a.pb(num % base); num /= base;}} inline int len() const {return a.size();} lnum & operator=(const lnum &l) {if (this != &l) {a = l.a; base = l.base;} return *this;} inline friend lnum operator+(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; int ln = l.len(), rn = r.len(); int n = max(ln, rn); ret.a.resize(n); int o = 0; for(int i = 0; i < n; ++i) {int s = o; if (i < ln) s += l.a[i]; if (i < rn) s += r.a[i]; o = s >= base; if (o) s -= base; ret.a[i] = s;} if (o) ret.a.push_back(1); return ret;} inline friend lnum operator-(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; int n = l.len(); int rn = r.len(); ret.a.resize(n); int o = 0; for(int i = 0; i < n; ++i) {int s = l.a[i] - o; if (i < rn) s -= r.a[i]; o = s < 0; if (o) s += base; ret.a[i] = s;} if (ret.len() > 1 && !ret.a.back()) ret.a.pop_back(); return ret;} inline friend lnum operator*(const lnum &l, const lnum &r) {lnum ret(0, l.base); int base = l.base; if (l.len() * r.len() > 1000000) {vector<cbase> fa (l.a.begin(), l.a.end()), fb (r.a.begin(), r.a.end()); int n = 1; while (n < max (l.len(), r.len())) n <<= 1; n <<= 1; fa.resize (n), fb.resize (n); fft (fa, false), fft (fb, false); for (int i = 0; i < n; ++i) fa[i] *= fb[i]; fft (fa, true); ret.a.resize(n); for (int i = 0; i < n; ++i) ret.a[i] = int (fa[i].real() + 0.5); int carry = 0; for (int i=0; i < n; ++i) {ret.a[i] += carry; carry = ret.a[i] / base; ret.a[i] %= base;}} else {ret.a.resize(l.len() + r.len()); for (int i = 0; i < l.len(); ++i) for (int j = 0, carry = 0; j < r.len() || carry; ++j) {long long cur = ret.a[i + j] + (ll)l.a[i] * (j < r.len() ? r.a[j] : 0) + carry; ret.a[i + j] = cur % base; carry = cur / base;}} while (ret.len() > 1 && !ret.a.back()) ret.a.pop_back(); return ret;} inline friend lnum operator/(const lnum &l, const int &r) {lnum ret(0, l.base); ret.a.resize(l.len()); int carry = 0; for(int i = l.len() - 1; i >= 0; --i) {long long cur = l.a[i] + (ll)carry * l.base; ret.a[i] = cur / r; carry = cur % r;} while (ret.len() > 1 && ret.a.back() == 0) ret.a.pop_back(); return ret;}  inline friend bool operator<(const lnum &l, const lnum &r) {if (l.len() < r.len()) return true; if (l.len() > r.len()) return false; int n = l.len(); for(int i = n - 1; i >= 0; --i) {if (l.a[i] < r.a[i]) return true; if (l.a[i] > r.a[i]) return false;} return false;} inline friend bool operator>(const lnum &l, const lnum &r) {return r < l;} inline friend bool operator==(const lnum &l, const lnum &r) {if (l.len() != r.len()) return false; int n = l.len(); for(int i = n - 1; i; --i) {if (l.a[i] != r.a[i]) return false;} return true;} inline friend bool operator!=(const lnum &l, const lnum &r) {return !(l == r);} inline void print() {if (base == 1000000000) {printf("%d", a.back()); for(int i = a.size() - 2; i >=0; --i) printf("%09d", a[i]);} else {for(int i = a.size() - 1; i >= 0; --i) printf("%d", a[i]);}}};

const int k = 1501;

struct node
{
    node * next[26];
    node * link;
    int cnt[11];
    int len;
    node()
    {
        link = 0;
        len = 0;
        memset(next, 0, sizeof(next));
        memset(cnt, 0, sizeof(cnt));
    }
    node(node * x)
    {
        link = x->link;
        len = x->len;
        memset(cnt, 0, sizeof(cnt));
        memcpy(next, x->next, sizeof(next));
    }
};

node * last, * root;

vector <node *> nodes;

void add(int c)
{
    node * cur = new node();
    nodes.pb(cur);
    cur->len = last->len + 1;
    node * p = last;
    for(; p && !p->next[c]; p = p->link)
        p->next[c] = cur;
    if (!p)
    {
        cur->link = root;
    }
    else
    {
        node * q = p->next[c];
        if (p->len + 1 == q->len)
        {
            cur->link = q;
        }
        else
        {
            node * cl = new node(q);
            nodes.pb(cl);
            cl->len = p->len + 1;
            for(; p && p->next[c] == q; p = p->link)
                p->next[c] = cl;
            q->link = cur->link = cl;
        }
    }
    last = cur;
}

void process(const string & s, int ind)
{
    last = root;
    int len = 0;
    for(char c : s)
    {
        ++len;
        if (last->next[c - 'a'] && last->next[c - 'a']->len == len)
        {
            last = last->next[c - 'a'];
        }
        else
        {
            add(c - 'a');
        }
        ++last->cnt[ind];
    }
}

bool cmp(node * l, node * r)
{
    return l->len > r->len;
}

string ok;

int main()
{
    last = root = new node();

    int l[11], r[11];
    string s[11];

    cin >> s[0];
    l[0] = 1, r[0] = s[0].length();

    int n;
    cin >> n;

    for(int i = 1; i <= n; ++i)
    {
        cin >> s[i] >> l[i] >> r[i];
    }

    ++n;
    for(int i = 0; i < n; ++i)
        process(s[i], i);

    sort(all(nodes), cmp);

    ll ans = 0;

    for(node * cur : nodes)
    {
        bool ok = true;
        for(int j = 0; j < n; ++j)
        {
            cur->link->cnt[j] += cur->cnt[j];
            if (cur->cnt[j] < l[j] || cur->cnt[j] > r[j])
                ok = false;
        }
        if (ok && cur->link)
            ans += cur->len - cur->link->len;
    }
    cout << ans << endl;
    return 0;
}


#include <algorithm>
#include <iostream>
#include <string.h>
#include <memory.h>
#include <sstream>
#include <fstream>
#include <cassert>
#include <cstdlib>
#include <complex>
#include <cctype>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>

using namespace std;

#define PII pair<int, int>
#define PLL pair<long long, long long>
#define F first
#define S second
#define ALL(x) x.begin(), x.end()
#define SZ(x) ((int)x.size())
#define div __div__
#define hash __hash__
#define prev __prev__
#define left __left__
#define right __right__
#define link __link__
#define next __next__

typedef vector<int> VI;
typedef vector<vector<int> > VII;
typedef long long LL;
typedef unsigned int UI;
typedef unsigned long long ULL;
typedef long double LD;

const LL INF = (LL)1e18;
const int N = 1000 * 1000 + 10;
const int S = 100 * 1000;

struct Node
{
    map<char, int> go;
    int suf, len;
    Node(): suf(-1), len(0) {}
};

Node t[N];
bool u[N];
int sz = 1, p = 0;

void add(char c)
{
    int v = sz++;
    t[v].len = t[p].len + 1;
    for (; p >= 0 && !t[p].go.count(c); p = t[p].suf)
        t[p].go[c] = v;
    if (p == -1)
    {
        t[v].suf = 0;
    }
    else
    {
        int to = t[p].go[c];
        if (t[to].len == t[p].len + 1)
        {
            t[v].suf = to;
        }
        else
        {
            int cl = sz++;
            t[cl].suf = t[to].suf;
            t[cl].len = t[p].len + 1;
            t[cl].go = t[to].go;
            for (; p >= 0 && t[p].go[c] == to; p = t[p].suf)
                t[p].go[c] = cl;
            t[v].suf = t[to].suf = cl;
        }
    }
    p = v;
}

LL dp[S][15];
LL l[15], r[15];
LL res = 0;
int n;
string s;

void dfs(int v)
{
    if (u[v])
        return;
    u[v] = true;
    for (int i = 0; i <= n; i++)
        dp[v][i] = 0;
    for (int i = 0; i <= n; i++)
        if (t[v].go.count(i))
            dp[v][i] = 1;
    for (auto c: t[v].go)
    {
        if (c.F < 'a' || c.F > 'z')
            continue;
        dfs(c.S);
        for (int i = 0; i <= n; i++)
            dp[v][i] += dp[c.S][i];
    }
    if (v)
    {
        bool ok = true;
        for (int i = 0; i <= n; i++)
            if (dp[v][i] > r[i] || dp[v][i] < l[i])
                ok = false;
        if (ok)
            res += t[v].len - t[t[v].suf].len;
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    cin >> s;
    for (int i = 0; i < s.length(); i++)
        add(s[i]);
    l[0] = 1;
    r[0] = INF;
    add(char(0));
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> s >> l[i] >> r[i];
        for (int j = 0; j < s.length(); j++)
            add(s[j]);
        add(char(i));
    }
    dfs(0);
    cout << res;

    return 0;
}


#include <algorithm>
#include <iostream>
#include <string.h>
#include <memory.h>
#include <sstream>
#include <fstream>
#include <cassert>
#include <cstdlib>
#include <complex>
#include <cctype>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>

using namespace std;

#define PII pair<int, int>
#define PLL pair<long long, long long>
#define F first
#define S second
#define ALL(x) x.begin(), x.end()
#define SZ(x) ((int)x.size())
#define div __div__
#define hash __hash__
#define prev __prev__
#define left __left__
#define right __right__
#define link __link__
#define next __next__

typedef vector<int> VI;
typedef vector<vector<int> > VII;
typedef long long LL;
typedef unsigned int UI;
typedef unsigned long long ULL;
typedef long double LD;

const LL INF = (LL)1e18;
const int N = 1000 * 1000 + 10;
const int S = 100 * 1000;

struct Node
{
    unordered_map<char, int> go;
    int suf, len;
    Node(): suf(-1), len(0) {}
};

Node t[N];
bool u[N];
int sz = 1, p = 0;

void add(char c)
{
    int v = sz++;
    t[v].len = t[p].len + 1;
    for (; p >= 0 && !t[p].go.count(c); p = t[p].suf)
        t[p].go[c] = v;
    if (p == -1)
    {
        t[v].suf = 0;
    }
    else
    {
        int to = t[p].go[c];
        if (t[to].len == t[p].len + 1)
        {
            t[v].suf = to;
        }
        else
        {
            int cl = sz++;
            t[cl].suf = t[to].suf;
            t[cl].len = t[p].len + 1;
            t[cl].go = t[to].go;
            for (; p >= 0 && t[p].go[c] == to; p = t[p].suf)
                t[p].go[c] = cl;
            t[v].suf = t[to].suf = cl;
        }
    }
    p = v;
}

LL dp[S][15];
LL l[15], r[15];
LL res = 0;
int n;
string s;

void dfs(int v)
{
    if (u[v])
        return;
    u[v] = true;
    for (int i = 0; i <= n; i++)
        dp[v][i] = 0;
    for (int i = 0; i <= n; i++)
        if (t[v].go.count(i))
            dp[v][i] = 1;
    for (auto c: t[v].go)
    {
        if (c.F < 'a' || c.F > 'z')
            continue;
        dfs(c.S);
        for (int i = 0; i <= n; i++)
            dp[v][i] += dp[c.S][i];
    }
    if (v)
    {
        bool ok = true;
        for (int i = 0; i <= n; i++)
            if (dp[v][i] > r[i] || dp[v][i] < l[i])
                ok = false;
        if (ok)
            res += t[v].len - t[t[v].suf].len;
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    cin >> s;
    for (int i = 0; i < s.length(); i++)
        add(s[i]);
    l[0] = 1;
    r[0] = INF;
    add(char(0));
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> s >> l[i] >> r[i];
        for (int j = 0; j < s.length(); j++)
            add(s[j]);
        add(char(i));
    }
    dfs(0);
    cout << res;

    return 0;
}


#include <cstdio>
#include <memory.h>

using namespace std;

const int N = 1000 * 1000 + 10;
const int S = 50 * 1000 + 10;

int go[N][37];
long long dp[N][11];
int l[11], r[11];
int suf[N], len[N];
int sz = 1, p = 0;
char s[S], u[N];
long long res = 0;
int n;

void init()
{
    for (int i = 0; i < N; i++)
    {
        u[i] = 0;
        for (int j = 0; j < 11; j++)
            dp[i][j] = 0;
        for (int j = 0; j < 37; j++)
            go[i][j] = -1;
    }
    suf[0] = -1;
    len[0] = 0;
}

void add(int c)
{
    int v = sz++;
    len[v] = len[p] + 1;
    for (; p >= 0 && go[p][c] == -1; p = suf[p])
        go[p][c] = v;
    if (p == -1)
    {
        suf[p] = 0;
    }
    else
    {
        int to = go[p][c];
        if (len[to] == len[p] + 1)
        {
            suf[v] = to;
        }
        else
        {
            int cl = sz++;
            memcpy(go[cl], go[to], 37 * sizeof(int));
            len[cl] = len[p] + 1;
            suf[cl] = suf[to];
            for (; p >= 0 && go[p][c] == to; p = suf[p])
                go[p][c] = cl;
            suf[v] = suf[to] = cl;
        }
    }
    p = v;
}

void dfs(int v)
{
    u[v] = 1;
    for (int i = 0; i <= n; i++)
        if (go[v][i] >= 0)
            dp[v][i] = 1;
    for (int i = n + 1; i < 37; i++)
        if (go[v][i] >= 0)
        {
            if (!u[go[v][i]])
                dfs(go[v][i]);
            for (int j = 0; j <= n; j++)
                dp[v][j] += dp[go[v][i]][j];
        }
    if (v && dp[v][0])
    {
        bool ok = true;
        for (int i = 1; i <= n && ok; i++)
            if (dp[v][i] < l[i] || dp[v][i] > r[i])
                ok = false;
        if (ok)
            res += len[v] - len[suf[v]];
    }
}

int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    init();
    scanf("%s", s);
    int len = strlen(s);
    scanf("%d", &n);
    for (int i = 0; i < len; i++)
        add(s[i] - 'a' + n + 1);
    add(0);
    for (int i = 1; i <= n; i++)
    {
        scanf("%s%d%d", s, &l[i], &r[i]);
        len = strlen(s);
        for (int j = 0; j < len; j++)
            add(s[j] - 'a' + n + 1);
        add(i);
    }
    dfs(0);
    printf("%I64d", res);
}


#include <cstdio>
#include <memory.h>

using namespace std;

const int N = 1000 * 1000 + 10;
const int S = 50 * 1000 + 10;

int go[N][37];
long long dp[N][11];
int l[11], r[11];
int suf[N], len[N];
int sz = 1, p = 0;
char s[S], u[N];
long long res = 0;
int n;

void init()
{
    for (int i = 0; i < N; i++)
    {
        u[i] = 0;
        for (int j = 0; j < 11; j++)
            dp[i][j] = 0;
        for (int j = 0; j < 37; j++)
            go[i][j] = -1;
    }
    suf[0] = -1;
    len[0] = 0;
}

void add(int c)
{
    int v = sz++;
    len[v] = len[p] + 1;
    for (; p >= 0 && go[p][c] == -1; p = suf[p])
        go[p][c] = v;
    if (p == -1)
    {
        suf[p] = 0;
    }
    else
    {
        int to = go[p][c];
        if (len[to] == len[p] + 1)
        {
            suf[v] = to;
        }
        else
        {
            int cl = sz++;
            memcpy(go[cl], go[to], 37 * sizeof(int));
            len[cl] = len[p] + 1;
            suf[cl] = suf[to];
            for (; p >= 0 && go[p][c] == to; p = suf[p])
                go[p][c] = cl;
            suf[v] = suf[to] = cl;
        }
    }
    p = v;
}

void dfs(int v)
{
    u[v] = 1;
    for (int i = 0; i <= n; i++)
        if (go[v][i] >= 0)
            dp[v][i] = 1;
    for (int i = n + 1; i < 37; i++)
        if (go[v][i] >= 0)
        {
            if (!u[go[v][i]])
                dfs(go[v][i]);
            for (int j = 0; j <= n; j++)
                dp[v][j] += dp[go[v][i]][j];
        }
    if (v && dp[v][0])
    {
        bool ok = true;
        for (int i = 1; i <= n && ok; i++)
            if (dp[v][i] < l[i] || dp[v][i] > r[i])
                ok = false;
        if (ok)
            res += len[v] - len[suf[v]];
    }
}

int main()
{
    init();
    scanf("%s", s);
    int len = strlen(s);
    scanf("%d", &n);
    for (int i = 0; i < len; i++)
        add(s[i] - 'a' + n + 1);
    add(0);
    for (int i = 1; i <= n; i++)
    {
        scanf("%s%d%d", s, &l[i], &r[i]);
        len = strlen(s);
        for (int j = 0; j < len; j++)
            add(s[j] - 'a' + n + 1);
        add(i);
    }
    dfs(0);
    printf("%I64d", res);
    return 0;
}


#include <algorithm>
#include <iostream>
#include <string.h>
#include <memory.h>
#include <sstream>
#include <fstream>
#include <cassert>
#include <cstdlib>
#include <complex>
#include <cctype>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>

using namespace std;

#define PII pair<int, int>
#define PLL pair<long long, long long>
#define F first
#define S second
#define ALL(x) x.begin(), x.end()
#define SZ(x) ((int)x.size())
#define div __div__
#define hash __hash__
#define prev __prev__
#define left __left__
#define right __right__
#define link __link__
#define next __next__

typedef vector<int> VI;
typedef vector<vector<int> > VII;
typedef long long LL;
typedef unsigned int UI;
typedef unsigned long long ULL;
typedef long double LD;

const LL INF = (LL)1e18;
const int N = 1000 * 1000 + 10;
const int S = 100 * 1000;

struct Node
{
    map<char, int> go;
    int suf, len;
    Node(): suf(-1), len(0) {}
};

Node t[N];
bool u[N];
int sz = 1, p = 0;

void add(char c)
{
    int v = sz++;
    t[v].len = t[p].len + 1;
    for (; p >= 0 && !t[p].go.count(c); p = t[p].suf)
        t[p].go[c] = v;
    if (p == -1)
    {
        t[v].suf = 0;
    }
    else
    {
        int to = t[p].go[c];
        if (t[to].len == t[p].len + 1)
        {
            t[v].suf = to;
        }
        else
        {
            int cl = sz++;
            t[cl].suf = t[to].suf;
            t[cl].len = t[p].len + 1;
            t[cl].go = t[to].go;
            for (; p >= 0 && t[p].go[c] == to; p = t[p].suf)
                t[p].go[c] = cl;
            t[v].suf = t[to].suf = cl;
        }
    }
    p = v;
}

LL dp[N][11];
LL l[11], r[11];
LL res = 0;
int n;
string s;

void dfs(int v)
{
    if (u[v])
        return;
    u[v] = true;
    for (int i = 0; i <= n; i++)
        dp[v][i] = 0;
    for (int i = 0; i <= n; i++)
        if (t[v].go.count(i))
            dp[v][i] = 1;
    for (auto c: t[v].go)
    {
        if (c.F < 'a' || c.F > 'z')
            continue;
        dfs(c.S);
        for (int i = 0; i <= n; i++)
            dp[v][i] += dp[c.S][i];
    }
    if (v)
    {
        bool ok = true;
        for (int i = 0; i <= n; i++)
            if (dp[v][i] > r[i] || dp[v][i] < l[i])
                ok = false;
        if (ok)
            res += t[v].len - t[t[v].suf].len;
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    fill(u, u + N, 0);
    cin >> s;
    for (int i = 0; i < s.length(); i++)
        add(s[i]);
    l[0] = 1;
    r[0] = INF;
    add(char(0));
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> s >> l[i] >> r[i];
        for (int j = 0; j < s.length(); j++)
            add(s[j]);
        add(char(i));
    }
    dfs(0);
    cout << res;

    return 0;
}


#include <cstdio>
#include <memory.h>

using namespace std;

const int N = 1000 * 1000 + 10;
const int S = 50 * 1000 + 10;

int go[N][37];
long long dp[N][11];
int l[11], r[11];
int suf[N], len[N];
int sz = 1, p = 0;
char s[S], u[N];
long long res = 0;
int n;

void init()
{
    for (int i = 0; i < N; i++)
    {
        u[i] = 0;
        for (int j = 0; j < 11; j++)
            dp[i][j] = 0;
        for (int j = 0; j < 37; j++)
            go[i][j] = -1;
    }
    suf[0] = -1;
    len[0] = 0;
}

void add(int c)
{
    int v = sz++;
    len[v] = len[p] + 1;
    for (; p >= 0 && go[p][c] == -1; p = suf[p])
        go[p][c] = v;
    if (p == -1)
    {
        suf[p] = 0;
    }
    else
    {
        int to = go[p][c];
        if (len[to] == len[p] + 1)
        {
            suf[v] = to;
        }
        else
        {
            int cl = sz++;
            memcpy(go[cl], go[to], 37 * sizeof(int));
            len[cl] = len[p] + 1;
            suf[cl] = suf[to];
            for (; p >= 0 && go[p][c] == to; p = suf[p])
                go[p][c] = cl;
            suf[v] = suf[to] = cl;
        }
    }
    p = v;
}

void dfs(int v)
{
    u[v] = 1;
    for (int i = 0; i <= n; i++)
        if (go[v][i] >= 0)
            dp[v][i] = 1;
    for (int i = n + 1; i < 37; i++)
        if (go[v][i] >= 0)
        {
            if (!u[go[v][i]])
                dfs(go[v][i]);
            for (int j = 0; j <= n; j++)
                dp[v][i] += dp[go[v][i]][j];
        }
    if (v && dp[v][0])
    {
        bool ok = true;
        for (int i = 1; i <= n && ok; i++)
            if (dp[v][i] < l[i] || dp[v][i] > r[i])
                ok = false;
        if (ok)
            res += len[v] - len[suf[v]];
    }
}

int main()
{
    init();
    scanf("%s", s);
    int len = strlen(s);
    scanf("%d", &n);
    for (int i = 0; i < len; i++)
        add(s[i] - 'a' + n + 1);
    add(0);
    for (int i = 1; i <= n; i++)
    {
        scanf("%s%d%d", s, &l[i], &r[i]);
        len = strlen(s);
        for (int j = 0; j < len; j++)
            add(s[j] - 'a' + n + 1);
        add(i);
    }
    dfs(0);
    printf("%I64d", res);
}


#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5;
int len[maxn], link[maxn];
map<char, int> to[maxn];
int mx[maxn], mn[maxn];
int sz = 1, last;

void add_letter(char c)
{
    int p = last;
    last = sz++;
    len[last] = len[p] + 1;
    for(; !to[p][c]; p = link[p]) to[p][c] = last;
    if(to[p][c] == last)
        return;
    int q = to[p][c];
    if(len[q] == len[p] + 1)
    {
        link[last] = q;
        return;
    }
    int cl = sz++;
    to[cl] = to[q];
    link[cl] = link[q];
    len[cl] = len[p] + 1;
    link[last] = link[q] = cl;
    for(; to[p][c] == q; p = link[p]) to[p][c] = cl;
}

vector<int> g[maxn];
map<int, int> occ[maxn];

int main()
{
    // freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    string s;
    cin >> s;
    for(auto c: s)
        add_letter(c);
    for(int i = 1; i < sz; i++)
    {
        mx[i] = len[i] + 1;
        mn[i] = len[link[i]] + 1;
        g[len[i]].push_back(i);
    }
    reverse(g, g + maxn);
    int z;
    cin >> z;
    while(z--)
    {
        for(int i = 0; i < sz; i++)
            occ[i].clear();
        string s;
        int l, r;
        cin >> s >> l >> r;
        int ln = 0;
        int v = 0;
        for(auto c: s)
        {
            while(v && !to[v][c]) v = link[v];
            ln = min(ln, len[v]);
            if(to[v][c]) v = to[v][c], ln++;
            occ[v][ln]++;
        }
        for(auto it: g)
        for(auto v: it)
        {
            occ[v][len[v]];
            occ[v][len[link[v]] + 1];
            for(auto it = --occ[v].end(); it != occ[v].begin(); it--)
            {
                auto t = it;
                t--;
                occ[v][t->first] += it->second;
            }
            bool ok = 0;
            for(auto it = occ[v].begin(); it != occ[v].end(); it++)
                if(it->second >= l && it->second <= r)
                {
                    mn[v] = max(mn[v], it->first);
                    ok = 1;
                    break;
                }
            if(!ok) mn[v] = len[v] + 1;
            for(auto it = --occ[v].end(); ; it--)
                if(it->second >= l && it->second <= r)
                {
                    mx[v] = min(mx[v], it->first + 1);
                    ok = 1;
                    break;
                }
                else if(it == occ[v].begin())
                {
                    break;
                }
            if(!ok) mx[v] = len[link[v]] + 1;
            occ[link[v]][len[link[v]]] += occ[v][len[link[v]] + 1];
        }
    }
    int ans = 0;
    for(int i = 1; i < sz; i++)
        ans += max(0, mx[i] - mn[i]);
    cout << ans << "\n";
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int maxn = 5e3 + 42, logn = 18;

int len[maxn], link[maxn][logn], cnt[maxn], used[maxn];
map<char, int> to[maxn];
int sz, last;

void add_letter(char c)
{
    int p = last;
    last = sz++;
    len[last] = len[p] + 1;
    for(; p != -1 && !to[p][c]; p = link[p][0]) to[p][c] = last;
    if(p == -1) return;
    int q = to[p][c];
    if(len[q] == len[p] + 1)
    {
        link[last][0] = q;
        return;
    }
    int cl = sz++;
    to[cl] = to[q];
    len[cl] = len[p] + 1;
    link[cl][0] = link[q][0];
    link[last][0] = link[q][0] = cl;
    for(; p != -1 && to[p][c] == q; p = link[p][0]) to[p][c] = cl;
}

void init()
{
    memset(len, 0, sizeof(len));
    memset(link, 0, sizeof(link));
    memset(cnt, 0, sizeof(cnt));
    memset(used, 0, sizeof(used));
    for(auto &it: to) it.clear();
    link[0][0] = -1;
    sz = 1;
    last = 0;
}

void dfs(int x)
{
    if(used[x]) return;
    used[x] = 1;
    for(auto it: to[x])
    {
        dfs(it.second);
        cnt[x] += cnt[it.second];
    }
}

void build(string s)
{
    init();
    s += '#';
    for(auto c: s) add_letter(c);
    cnt[last] = 1;
    dfs(0);
    for(int j = 1; j < logn; j++)
        for(int i = 0; i < sz; i++)
            if(link[i][j - 1] != -1) link[i][j] = link[link[i][j - 1]][j - 1];
            else link[i][j] = -1;
}

int bound(int x, int n, bool mod)
{
    for(int i = logn - 1; i >= 0; i--)
    {
        if(link[x][i] == -1) continue;
        if(cnt[link[x][i]] <= n) x = link[x][i];
    }
    if(mod && cnt[x] < n) x = link[x][0];
    return x;
}

void feed(string s, int l, int r, int *mn_len, int *mx_len)
{
    int cur = 0;
    for(int i = 0; i < s.size(); i++)
    {
        while(cur != -1 && !to[cur][s[i]]) cur = link[cur][0];
        if(cur == -1) cur = 0;
        else cur = to[cur][s[i]];
        mn_len[i] = min(mn_len[i], len[bound(cur, l, 0)]);
        mx_len[i] = max(mx_len[i], len[bound(cur, r, 1)]);
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    string s;
    cin >> s;
    int m = s.size();
    int n;
    cin >> n;
    int min_suf[m], max_suf[m];
    memset(min_suf, 63, sizeof(min_suf));
    memset(max_suf, 00, sizeof(max_suf));
    while(n--)
    {
        string p;
        int l, r;
        cin >> p >> l >> r;
        build(p);
        feed(s, l, r, min_suf, max_suf);
    }
    int ans = 0;
    for(int i = 0; i < m; i++)
        ans += max_suf[i] - min_suf[i];
    cout << ans << "\n";
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int maxn = 5e3 + 42, logn = 18;

int len[maxn], link[maxn][logn], cnt[maxn], used[maxn];
map<char, int> to[maxn];
int sz, last;

void add_letter(char c)
{
    int p = last;
    last = sz++;
    len[last] = len[p] + 1;
    for(; p != -1 && !to[p][c]; p = link[p][0]) to[p][c] = last;
    if(p == -1) return;
    int q = to[p][c];
    if(len[q] == len[p] + 1)
    {
        link[last][0] = q;
        return;
    }
    int cl = sz++;
    to[cl] = to[q];
    len[cl] = len[p] + 1;
    link[cl][0] = link[q][0];
    link[last][0] = link[q][0] = cl;
    for(; p != -1 && to[p][c] == q; p = link[p][0]) to[p][c] = cl;
}

void init()
{
    memset(len, 0, sizeof(len));
    memset(link, 0, sizeof(link));
    memset(cnt, 0, sizeof(cnt));
    memset(used, 0, sizeof(used));
    for(auto &it: to) it.clear();
    link[0][0] = -1;
    sz = 1;
    last = 0;
}

void dfs(int x)
{
    if(used[x]) return;
    used[x] = 1;
    for(auto it: to[x])
    {
        dfs(it.second);
        cnt[x] += cnt[it.second];
    }
}

void build(string s)
{
    init();
    s += '#';
    for(auto c: s) add_letter(c);
    cnt[last] = 1;
    dfs(0);
    for(int j = 1; j < logn; j++)
        for(int i = 0; i < sz; i++)
            if(link[i][j - 1] != -1) link[i][j] = link[link[i][j - 1]][j - 1];
            else link[i][j] = -1;
}

int bound(int x, int n, bool mod)
{
    for(int i = logn - 1; i >= 0; i--)
    {
        if(link[x][i] == -1) continue;
        if(cnt[link[x][i]] <= n) x = link[x][i];
    }
    if(mod && cnt[x] < n && link[x][0] != -1) x = link[x][0];
    return x;
}

void feed(string s, int l, int r, int *mn_len, int *mx_len)
{
    int cur = 0, ln = 0;
    for(int i = 0; i < s.size(); i++)
    {
        while(cur != -1 && !to[cur][s[i]]) cur = link[cur][0];
        if(cur == -1) cur = 0;
        else ln = min(ln, len[cur]), cur = to[cur][s[i]];
        ln++;
        if(r < cnt[cur]) mn_len[i] = max(mn_len[i], 1 + min(ln, len[cur]));
        else mn_len[i] = max(mn_len[i], min(ln, len[bound(cur, r, 1)]));
        if(l == 0) mx_len[i] = min(mx_len[i], i + 1);
        else mx_len[i] = min(mx_len[i], min(ln, len[bound(cur, l, 0)]));
        //cout << s[i] << ' ' << mn_len[i] << ' ' << mx_len[i] << ' ' << len[cur] << "\n";
    }
    //cout << "\n";
}

int main()
{
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    string s;
    cin >> s;
    int m = s.size();
    int n;
    cin >> n;
    int min_suf[m], max_suf[m];
    memset(min_suf, 00, sizeof(min_suf));
    memset(max_suf, 63, sizeof(max_suf));
    while(n--)
    {
        string p;
        int l, r;
        cin >> p >> l >> r;
        build(p);
        feed(s, l, r, min_suf, max_suf);
    }
    int ans = 0;
    for(int i = 0; i < m; i++)
        ans += max(0, max_suf[i] - min_suf[i] + 1);
    cout << ans << "\n";
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int maxn = 5e3 + 42, logn = 18;

int len[maxn], link[maxn][logn], cnt[maxn], used[maxn];
map<char, int> to[maxn];
int sz, last;

void add_letter(char c)
{
    int p = last;
    last = sz++;
    len[last] = len[p] + 1;
    for(; p != -1 && !to[p][c]; p = link[p][0]) to[p][c] = last;
    if(p == -1) return;
    int q = to[p][c];
    if(len[q] == len[p] + 1)
    {
        link[last][0] = q;
        return;
    }
    int cl = sz++;
    to[cl] = to[q];
    len[cl] = len[p] + 1;
    link[cl][0] = link[q][0];
    link[last][0] = link[q][0] = cl;
    for(; p != -1 && to[p][c] == q; p = link[p][0]) to[p][c] = cl;
}

void init()
{
    memset(len, 0, sizeof(len));
    memset(link, 0, sizeof(link));
    memset(cnt, 0, sizeof(cnt));
    memset(used, 0, sizeof(used));
    for(auto &it: to) it.clear();
    link[0][0] = -1;
    sz = 1;
    last = 0;
}

void dfs(int x)
{
    if(used[x]) return;
    used[x] = 1;
    for(auto it: to[x])
    {
        dfs(it.second);
        cnt[x] += cnt[it.second];
    }
}

void build(string s)
{
    init();
    s += '#';
    for(auto c: s) add_letter(c);
    cnt[last] = 1;
    dfs(0);
    for(int j = 1; j < logn; j++)
        for(int i = 0; i < sz; i++)
            if(link[i][j - 1] != -1) link[i][j] = link[link[i][j - 1]][j - 1];
            else link[i][j] = -1;
}

int bound(int x, int n, bool mod)
{
    for(int i = logn - 1; i >= 0; i--)
    {
        if(link[x][i] == -1) continue;
        if(cnt[link[x][i]] <= n) x = link[x][i];
    }
    if(mod && cnt[x] < n && link[x][0] != -1) x = link[x][0];
    return x;
}

void feed(string s, int l, int r, int *mn_len, int *mx_len)
{
    int cur = 0, ln = 0;
    for(int i = 0; i < s.size(); i++)
    {
        while(cur != -1 && !to[cur][s[i]]) cur = link[cur][0];
        if(cur == -1) cur = 0;
        else ln = min(ln, len[cur]), cur = to[cur][s[i]];
        ln++;
        if(r < cnt[cur]) mn_len[i] = max(mn_len[i], 1 + min(ln, len[cur]));
        else mn_len[i] = max(mn_len[i], min(ln, len[bound(cur, r, 1)]));
        if(l == 0) mx_len[i] = min(mx_len[i], i + 1);
        else mx_len[i] = min(mx_len[i], min(ln, len[bound(cur, l, 0)]));
        //cout << s[i] << ' ' << mn_len[i] << ' ' << mx_len[i] << ' ' << len[cur] << "\n";
    }
    //cout << "\n";
}

int main()
{
    freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    string s;
    cin >> s;
    int m = s.size();
    int n;
    cin >> n;
    int min_suf[m], max_suf[m];
    memset(min_suf, 00, sizeof(min_suf));
    memset(max_suf, 63, sizeof(max_suf));
    while(n--)
    {
        string p;
        int l, r;
        cin >> p >> l >> r;
        build(p);
        feed(s, l, r, min_suf, max_suf);
    }
    int ans = 0;
    for(int i = 0; i < m; i++)
        ans += max(0, max_suf[i] - min_suf[i] + 1);
    cout << ans << "\n";
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int maxn = 5e3 + 42, logn = 18;

int len[maxn], link[maxn][logn], cnt[maxn], used[maxn];
map<char, int> to[maxn];
int sz, last;

void add_letter(char c)
{
    int p = last;
    last = sz++;
    len[last] = len[p] + 1;
    for(; p != -1 && !to[p][c]; p = link[p][0]) to[p][c] = last;
    if(p == -1) return;
    int q = to[p][c];
    if(len[q] == len[p] + 1)
    {
        link[last][0] = q;
        return;
    }
    int cl = sz++;
    to[cl] = to[q];
    len[cl] = len[p] + 1;
    link[cl][0] = link[q][0];
    link[last][0] = link[q][0] = cl;
    for(; p != -1 && to[p][c] == q; p = link[p][0]) to[p][c] = cl;
}

void init()
{
    memset(len, 0, sizeof(len));
    memset(link, 0, sizeof(link));
    memset(cnt, 0, sizeof(cnt));
    memset(used, 0, sizeof(used));
    for(auto &it: to) it.clear();
    link[0][0] = -1;
    sz = 1;
    last = 0;
}

void dfs(int x)
{
    if(used[x]) return;
    used[x] = 1;
    for(auto it: to[x])
    {
        dfs(it.second);
        cnt[x] += cnt[it.second];
    }
}

void build(string s)
{
    init();
    s += '#';
    for(auto c: s) add_letter(c);
    cnt[last] = 1;
    dfs(0);
    for(int j = 1; j < logn; j++)
        for(int i = 0; i < sz; i++)
            if(link[i][j - 1] != -1) link[i][j] = link[link[i][j - 1]][j - 1];
            else link[i][j] = -1;
}

int bound(int x, int n, bool mod)
{
    for(int i = logn - 1; i >= 0; i--)
    {
        if(link[x][i] == -1) continue;
        if(cnt[link[x][i]] <= n) x = link[x][i];
    }
    if(mod && cnt[x] < n && link[x][0] != -1) x = link[x][0];
    return x;
}

void feed(string s, int l, int r, int *mn_len, int *mx_len)
{
    int cur = 0, ln = 0;
    for(int i = 0; i < s.size(); i++)
    {
        while(cur != -1 && !to[cur][s[i]]) cur = link[cur][0];
        if(cur == -1) cur = 0;
        else ln = min(ln, len[cur]), cur = to[cur][s[i]];
        ln++;
        if(r < cnt[cur]) mn_len[i] = max(mn_len[i], 1 + min(ln, len[cur]));
        else mn_len[i] = max(mn_len[i], min(ln, 1 + len[link[bound(cur, r, 1)][0]]));
        if(l == 0) mx_len[i] = min(mx_len[i], i + 1);
        else mx_len[i] = min(mx_len[i], min(ln, len[bound(cur, l, 0)]));
        //cout << s[i] << ' ' << mn_len[i] << ' ' << mx_len[i] << ' ' << len[cur] << "\n";
    }
    //cout << "\n";
}

int main()
{
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    string s;
    cin >> s;
    int m = s.size();
    int n;
    cin >> n;
    int min_suf[m], max_suf[m];
    memset(min_suf, 00, sizeof(min_suf));
    memset(max_suf, 63, sizeof(max_suf));
    while(n--)
    {
        string p;
        int l, r;
        cin >> p >> l >> r;
        build(p);
        feed(s, l, r, min_suf, max_suf);
    }
    int ans = 0;
    for(int i = 0; i < m; i++)
        ans += max(0, max_suf[i] - min_suf[i] + 1);
    cout << ans << "\n";
    return 0;
}


#include <stdio.h>
#include <string.h>

const int MAXN = 12, LEN = 601000, SIGMA = 26;
char s[50001];
int n;
int l[MAXN], r[MAXN];
struct sam {
    int l;
    sam *f, *ch[SIGMA + 1];
    int c[MAXN];
}pool[LEN * 2], *root, *tail, *pos[LEN * 2];
int psz;
int ans;

sam *init_node(sam *p, int k)
{
    memset(p->ch, 0, sizeof(p->ch));
    memset(p->c, 0, sizeof(p->c));
    p->f = 0; p->l = 0; p->c[k] = 1;
    return p;
}

void sam_add(int v, int k)
{
    sam *p = init_node(pool + psz++, k), *i;
    p->l = tail->l + 1;
    for (i = tail; i && !i->ch[v]; i = i->f) i->ch[v] = p;
    if (!i) {
        p->f = root;
    } else if (i->ch[v]->l == i->l + 1) {
        p->f = i->ch[v];
    } else {
        sam *q = pool + psz++, *r = i->ch[v];
        *q = *r;
        memset(q->c, 0, sizeof(q->c));
        q->l = i->l + 1;
        p->f = r->f = q;
        for (; i && i->ch[v] == r; i = i->f) i->ch[v] = q;
    }
    tail = p;
}

void csort()
{
    static int c[LEN * 2];
    memset(c, 0, sizeof(c));
    for (int i = 0; i < psz; ++i) ++c[pool[i].l];
    for (int i = 1; i < psz; ++i) c[i] += c[i - 1];
    for (int i = 0; i < psz; ++i) pos[--c[pool[i].l]] = &pool[i];
}

void add(char *s, int k)
{
    for (; *s; ++s) sam_add(*s - 'a', k);
    sam_add(SIGMA, n + 1);
}

void init()
{
    psz = 1; init_node(root = tail = pool, 0);
    scanf("%s%d", s, &n);
    add(s, 0);
    for (int i = 1; i <= n; ++i) {
        scanf("%s%d%d", s, &l[i], &r[i]);
        add(s, i);
    }
}

bool chk(int c[])
{
    if (!c[0]) return false;
    for (int i = 1; i <= n; ++i) {
        if (c[i] < l[i] || c[i] > r[i]) return false;
    }
    return true;
}

void solve()
{
    ans = 0;
    for (int i = psz - 1; i; --i) {
        if (chk(pos[i]->c)) ans += pos[i]->l - pos[i]->f->l;
        for (int j = 0; j <= n; ++j) pos[i]->f->c[j] += pos[i]->c[j];
    }
}

int main()
{
    init();
    csort();
    solve();
    printf("%d\n", ans);
}


#include <stdio.h>
#include <string.h>

const int MAXN = 12, LEN = 60001, SIGMA = 26;
char s[50001];
int n;
int l[MAXN], r[MAXN];
struct sam {
    int l;
    sam *f, *ch[SIGMA + 1];
    int c[MAXN];
}pool[LEN * 2], *root, *tail, *pos[LEN * 2];
int psz;
int ans;

sam *init_node(sam *p, int k)
{
    memset(p->ch, 0, sizeof(p->ch));
    memset(p->c, 0, sizeof(p->c));
    p->f = 0; p->l = 0; p->c[k] = 1;
    return p;
}

void sam_add(int v, int k)
{
    sam *p = init_node(pool + psz++, k), *i;
    p->l = tail->l + 1;
    for (i = tail; i && !i->ch[v]; i = i->f) i->ch[v] = p;
    if (!i) {
        p->f = root;
    } else if (i->ch[v]->l == i->l + 1) {
        p->f = i->ch[v];
    } else {
        sam *q = pool + psz++, *r = i->ch[v];
        *q = *r;
        q->l = i->l + 1;
        p->f = r->f = q;
        for (; i && i->ch[v] == r; i = i->f) i->ch[v] = q;
    }
    tail = p;
}

void csort()
{
    static int c[LEN * 2];
    memset(c, 0, sizeof(c));
    for (int i = 0; i < psz; ++i) ++c[pool[i].l];
    for (int i = 1; i < psz; ++i) c[i] += c[i - 1];
    for (int i = 0; i < psz; ++i) pos[--c[pool[i].l]] = &pool[i];
}

void add(char *s, int k)
{
    for (; *s; ++s) sam_add(*s - 'a', k);
    sam_add(SIGMA, n + 1);
}

void init()
{
    psz = 1; init_node(root = tail = pool, 0);
    scanf("%s%d", s, &n);
    add(s, 0);
    for (int i = 1; i <= n; ++i) {
        scanf("%s%d%d", s, &l[i], &r[i]);
        add(s, i);
    }
}

bool chk(int c[])
{
    if (!c[0]) return false;
    for (int i = 1; i <= n; ++i) {
        if (c[i] < l[i] || c[i] > r[i]) return false;
    }
    return true;
}

void solve()
{
    ans = 0;
    for (int i = psz - 1; i; --i) {
        if (chk(pos[i]->c)) ans += pos[i]->l - pos[i]->f->l;
        for (int j = 0; j <= n; ++j) pos[i]->f->c[j] += pos[i]->c[j];
    }
}

int main()
{
    init();
    csort();
    solve();
    printf("%d\n", ans);
}


#include <stdio.h>
#include <string.h>

const int MAXN = 12, LEN = 60100, SIGMA = 26;
char s[50001];
int n;
int l[MAXN], r[MAXN];
struct sam {
    int l;
    sam *f, *ch[SIGMA + 1];
    int c[MAXN];
}pool[LEN * 2], *root, *tail, *pos[LEN * 2];
int psz;
int ans;

sam *init_node(sam *p, int k)
{
    memset(p->ch, 0, sizeof(p->ch));
    memset(p->c, 0, sizeof(p->c));
    p->f = 0; p->l = 0; p->c[k] = 1;
    return p;
}

void sam_add(int v, int k)
{
    sam *p = init_node(pool + psz++, k), *i;
    p->l = tail->l + 1;
    for (i = tail; i && !i->ch[v]; i = i->f) i->ch[v] = p;
    if (!i) {
        p->f = root;
    } else if (i->ch[v]->l == i->l + 1) {
        p->f = i->ch[v];
    } else {
        sam *q = pool + psz++, *r = i->ch[v];
        *q = *r;
        memset(q->c, 0, sizeof(q->c));
        q->l = i->l + 1;
        p->f = r->f = q;
        for (; i && i->ch[v] == r; i = i->f) i->ch[v] = q;
    }
    tail = p;
}

void csort()
{
    static int c[LEN * 2];
    memset(c, 0, sizeof(c));
    for (int i = 0; i < psz; ++i) ++c[pool[i].l];
    for (int i = 1; i < psz; ++i) c[i] += c[i - 1];
    for (int i = 0; i < psz; ++i) pos[--c[pool[i].l]] = &pool[i];
}

void add(char *s, int k)
{
    for (; *s; ++s) sam_add(*s - 'a', k);
    sam_add(SIGMA, n + 1);
}

void init()
{
    psz = 1; init_node(root = tail = pool, 0);
    scanf("%s%d", s, &n);
    add(s, 0);
    for (int i = 1; i <= n; ++i) {
        scanf("%s%d%d", s, &l[i], &r[i]);
        add(s, i);
    }
}

bool chk(int c[])
{
    if (!c[0]) return false;
    for (int i = 1; i <= n; ++i) {
        if (c[i] < l[i] || c[i] > r[i]) return false;
    }
    return true;
}

void solve()
{
    ans = 0;
    for (int i = psz - 1; i; --i) {
        if (chk(pos[i]->c)) ans += pos[i]->l - pos[i]->f->l;
        for (int j = 0; j <= n; ++j) pos[i]->f->c[j] += pos[i]->c[j];
    }
}

int main()
{
    init();
    csort();
    solve();
    printf("%d\n", ans);
}


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1100005;

int root , last , nodecnt;
int u[N][27] , val[N] , par[N] , bel[N];
inline int newnode(int _val , int _id = -1) {
    ++ nodecnt;
    val[nodecnt] = _val , par[nodecnt] = 0 , bel[nodecnt] = _id;
    return nodecnt;
}
void extend(int c , int id = -1) {
    int p = last , np = newnode(val[p] + 1 , id);
    while (p && u[p][c] == 0)
        u[p][c] = np , p = par[p];
    if (p == 0)
        par[np] = root;
    else {
        int q = u[p][c];
        if (val[p] + 1 == val[q]) {
            par[np] = q;
        } else {
            int nq = newnode(val[p] + 1);
            memcpy(u[nq] , u[q] , sizeof(u[q]));
            par[nq] = par[q];
            par[q] = par[np] = nq;
            while (p && u[p][c] == q)
                u[p][c] = nq , p = par[p];
        }
    }
    last = np;
}

char str[50005] , t[50005];
int n , L[10] , R[10];
vector<int> e[N];
int cnt[N][10] , vis[N];
bool vaild[N];

void dfs(int x) {
    if (~bel[x]) cnt[x][bel[x]] = 1;
    for (auto y : e[x]) {
        dfs(y);
        for (int i = 0 ; i < n ; ++ i)
            cnt[x][i] += cnt[y][i];
    }
    //printf("%d : " , x);
    //for (int i = 0 ; i < n ; ++ i)
    //    printf("%d%c" , cnt[x][i] , " \n"[i + 1 == n]);
    for (int i = 0 ; i < n ; ++ i)
        if (cnt[x][i] < L[i] || cnt[x][i] > R[i])
            return;
    vaild[x] = 1;
    //printf("%d\n" , x);
}

void work() {
    nodecnt = 0;
    root = last = newnode(0);
    scanf("%s%d" , t , &n);
    for (int i = 0 ; t[i] ; ++ i)
        extend(t[i] - 'a');
    extend(26);
    for (int i = 0 ; i < n ; ++ i) {
        scanf("%s%d%d" , str , &L[i] , &R[i]);
        for (int j = 0 ; str[j] ; ++ j)
            extend(str[j] - 'a' , i);
        extend(26);
    }
    for (int i = 2 ; i <= nodecnt ; ++ i)
        e[par[i]].push_back(i);
    dfs(1);
    int x = 1 , l = 0;
    LL res = 0;
    for (int i = 0 ; t[i] ; ++ i) {
        int c = t[i] - 'a';
        while (x && !u[x][c])
            x = par[x] , l = val[x];
        u[x][c] ? (x = u[x][c] , ++ l) : (x = 1 , l = 0);

        int y = x , p = l;
        while (y) {
            if (vis[y]) break;
            vis[y] = 1;
            if (vaild[y]) {
                //printf("%d %d\n" , y , p - val[par[y]]);
                res += p - val[par[y]];
                vis[y] = 1;
            }
            y = par[y] , p = val[y];
        }
    }
    cout << res << endl;
}

int main() {
    work();
    return 0;
}


import java.util.List;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Collection;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author AlexFetisov
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskG solver = new TaskG();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskG {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        String s = in.nextString();
        n = in.nextInt();
        auto = new SuffixAuto();
        auto.addWord(1 << n, s);
        rangeLeft = new int[n];
        rangeRight = new int[n];
        for (int i = 0; i < n; ++i) {
            s = in.nextString();
            auto.addWord(1 << i, s);
            rangeLeft[i] = in.nextInt();
            rangeRight[i] = in.nextInt();
        }
        TreeNode root = auto.root.toTree();
        prepareTree(root);
        reachable = new boolean[size];
        numberOf = new int[size][n];
        long res = 0;
        for (int i = size-1; i >= 0; --i) {
            reachable[i] = BitUtils.checkBit(mask[i], n);
            for (int j = 0; j < n; ++j) if (BitUtils.checkBit(mask[i], j)) {
                numberOf[i][j]++;
            }
            for (int j = tree.first[i]; j != -1; j = tree.next[j]) {
                int to = tree.to[j];
                if (to != parent[i]) {
                    reachable[i] |= reachable[to];
                    for (int k = 0; k < n; ++k) {
                        numberOf[i][k] += numberOf[to][k];
                    }
                }
            }
            if (reachable[i]) {
                boolean bad = false;
                for (int j = 0; j < n; ++j) {
                    if (!(rangeLeft[j] <= numberOf[i][j] && rangeRight[j] >= numberOf[i][j])) {
                        bad = true;
                        break;
                    }
                }
                if (!bad) {
                    res += parentLen[i];
                }
            }
        }
        out.println(res);
    }

    SuffixAuto auto;
    int n;
    int[] rangeLeft;
    int[] rangeRight;
    Graph tree;
    int size;
    int[] mask;
    int[] parent;
    int[] parentLen;
    int[][] numberOf;
    boolean[] reachable;

    void prepareTree(TreeNode root) {
        size = root.size();
        mask = new int[size];
        parent = new int[size];
        parentLen = new int[size];
        tree = new Graph();
        tree.initGraphWithCost(size, size);
        TreeNode[] q = new TreeNode[size * 2];
        int[] id = new int[size * 2];
        int qSize = 0;
        id[qSize] = 0;
        q[qSize++] = root;
        parent[0] = -1;
        int count = 1;
        for (int i = 0; i < qSize; ++i) {
            TreeNode v = q[i];
            int idx = id[i];
            mask[idx] = v.mask;
            for (int j = 0; j < v.next.size(); ++j) {
                tree.addEdgeWithCost(idx, count + j, v.lengths.get(j));
                id[qSize] = count + j;
                q[qSize++] = v.next.get(j);
                parent[count + j] = idx;
                parentLen[count + j] = v.lengths.get(j);
            }
            count += v.next.size();
        }
    }

    class TreeNode {
        List<TreeNode> next;
        List<Integer> lengths;
        int mask;

        int size() {
            int r = 1;
            for (TreeNode nxt : next) {
                r += nxt.size();
            }
            return r;
        }
    }

    class SuffixAuto {
        class Vertex {
            Vertex suffixLink = null;
            int length = 0;
            Vertex[] edge;
            int terminal = 0;

            TreeNode to;
            int toLen = -1;

            TreeNode toTree() {
                if (to != null) return to;
                Vertex one = null;
                int count = 0;
                for (int i = 0; i < 26; ++i) if (edge[i] != null) {
                    ++count;
                    one = edge[i];
                }
                if (count == 1 && terminal == 0) {
                    to = one.toTree();
                    toLen = one.toLen + 1;
                } else {
                    to = new TreeNode();
                    to.mask = terminal;
                    to.next = new ArrayList<TreeNode>(count);
                    to.lengths = new ArrayList<Integer>(count);
                    for (int i = 0; i < 26; ++i) {
                        if (edge[i] != null) {
                            to.next.add(edge[i].toTree());
                            to.lengths.add(edge[i].toLen + 1);
                        }
                    }
                    toLen = 0;
                }
                return to;
            }

            Vertex(int length) {
                this.length = length;
                edge = new Vertex[26];
                Arrays.fill(edge, null);
            }

            Vertex(Vertex v, int length) {
                this.length = length;
                this.terminal = v.terminal;
                edge = v.edge.clone();
            }
        }

        Vertex root;
        Vertex last;

        SuffixAuto() {
            root = new Vertex(0);
        }

        void addWord(int bit, String s) {
            last = root;
            char[] c = s.toCharArray();
            for (char C : c) {
                addChar(C - 'a');
            }
            while (last != null) {
                last.terminal |= bit;
                last = last.suffixLink;
            }
        }

        private void addChar(int c) {
            Vertex cur = last;
            last = new Vertex(cur.length + 1);
            for (; cur != null && cur.edge[c] == null; cur = cur.suffixLink) cur.edge[c] = last;
            if (cur == null) {
                last.suffixLink = root;
            } else {
                Vertex q = cur.edge[c];
                if (q.length == cur.length + 1) {
                    last.suffixLink = q;
                } else {
                    Vertex r = new Vertex(q, cur.length + 1);
                    r.suffixLink = q.suffixLink;
                    q.suffixLink = r;
                    last.suffixLink = r;
                    for (; cur != null && cur.edge[c] == q; cur = cur.suffixLink) cur.edge[c] = r;
                }
            }
        }
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
    }

    public String nextLine() {
        try {
            return reader.readLine().trim();
        } catch (IOException e) {
            return null;
        }
    }

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(nextString());
    }

}

class BitUtils {
    public static boolean checkBit(int mask, int bit) {
        return (mask & (1 << bit)) > 0;
    }

}

class Graph {
    public int[] from;
    public int[] to;
    public int[] first;
    public int[] next;
    public int[] cost;
    public int nVertex;
    public int nEdges;
    public int curEdge;

    public Graph() {}

    public void initGraphWithCost(int n, int m) {
        curEdge = 0;
        nVertex = n;
        nEdges = m;
        from = new int[m * 2];
        to = new int[m * 2];
        first = new int[n];
        next = new int[m * 2];
        cost = new int[m * 2];
        Arrays.fill(first, -1);
    }

    public void addEdgeWithCost(int a, int b, int c) {
        next[curEdge] = first[a];
        first[a] = curEdge;
        to[curEdge] = b;
        from[curEdge] = a;
        cost[curEdge] = c;
        ++curEdge;

        next[curEdge] = first[b];
        first[b] = curEdge;
        to[curEdge] = a;
        from[curEdge] = b;
        cost[curEdge] = c;
        ++curEdge;
    }

}


#include <algorithm>

#include <stdio.h>

#include <memory.h>

#include <string.h>

#include <queue>

#include <stack>

#include <cmath>

#include <iostream>

#include <set>

#include <string>

#include <map>

using namespace std;

#define NN 560000

#define IMAX 2147483647

#define eprintf(...) fprintf(stderr, __VA_ARGS__)

#define smax(a, b) a=max(a, b)

#define smin(a, b) a=min(a, b)

typedef long long INT;

typedef pair<int, int> pii;

int l[100], r[100];

struct suffixautomata {

	struct Node {

		int deep, fail, val[12], next[38];

		INT cnt;

		void clear() {

			deep=fail=0;

			cnt=0;

			memset(next, 0, sizeof(next));

			memset(val, 0, sizeof(val));

		}

	};

	int size, endp;

	Node node[2*NN];

	int cnt[2*NN], st[2*NN];

	void init() {

		for (int i=0; i<38; i++) node[0].next[i]=1;

		node[0].deep=-1;

		node[1].clear();

		size=2; endp=1;

	}

	void insert(int c, int id) {

		int p, p1, p2;

		p=size++;

		node[p].clear();

		node[p].deep=node[endp].deep+1;

		while (node[endp].next[c]==0) {

			node[endp].next[c]=p;

			endp=node[endp].fail;

		}

		p1=node[endp].next[c];

		if (node[p1].deep==node[endp].deep+1) node[p].fail=p1;

		else {

			p2=size++;

			node[p2]=node[p1]; node[p].fail=node[p1].fail=p2;

			node[p2].deep=node[endp].deep+1;

			while (node[endp].next[c]==p1) {

				node[endp].next[c]=p2;

				endp=node[endp].fail;

			}

		}

		endp=p;

	}

	void make(char *a) {

		int i, x, j, k, len;

		len=strlen(a);

		for (i=0; i<len; i++) {

			if ('a'<=a[i] && a[i]<='z') insert(a[i]-'a', i);

			else insert(26+a[i]-'A', i);

		}

		for (i=0; i<=len; i++) cnt[i]=0;

		for (i=1; i<size; i++) cnt[node[i].deep]++;

		for (i=1; i<=len; i++) cnt[i]+=cnt[i-1];

		for (i=1; i<size; i++) st[cnt[node[i].deep]--]=i;

		for (i=size-1; i>0; i--) {

			x=st[i];

			for (k=0; k<26; k++) {

				if (node[x].next[k]==0) continue;

				for (j=0; j<12; j++)

					node[x].val[j]+=node[node[x].next[k]].val[j];

			}

			for (k=0; k<12; k++) {

				if (node[x].next[26+k]==0) continue;

				node[x].val[k]++;

			}

		}

		node[1].cnt=1;

		for (i=1; i<size; i++) {

			x=st[i];

			for (k=0; k<26; k++) {

				if (node[x].next[k]==0) continue;

				node[node[x].next[k]].cnt+=node[x].cnt;

			}

		}

	}

	INT visit(int n) {

		int i, j, u, v;

		INT ans=0;

		for (i=2; i<size; i++) {

			if (node[i].val[0]==0) continue;

			for (j=0; j<n; j++) {

				if (node[i].val[j+1]<l[j] || node[i].val[j+1]>r[j])

					break;

			}

			if (j==n) ans+=node[i].cnt;

		}

		return ans;

	}

};

suffixautomata sam;

char str[NN], pat[NN];

int main() {

	int n, i;

	char tmp[100];

	scanf("%s", str);

	tmp[0]='A'; tmp[1]=0; strcat(str, tmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {

		scanf("%s%d%d", pat, l+i, r+i);

		strcat(str, pat);

		tmp[0]='A'+i+1; tmp[1]=0;

		strcat(str, tmp);

	}

	sam.init();

	sam.make(str);

	printf("%I64d\n", sam.visit(n));

	return 0;

}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], mp[20][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

bool Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) ret=0;
	else {
		for (j=i; j<L[k]; j++) {
			if (mp[k][j]<len) break;
		}
		ret=j-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return true;
	return false;

}

int main() {

	int ls, i, j, k, len, t;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	for (k=0; k<n; k++) {
		for (i=0; i<L[k]-1; i++) {
			for (j=0; j<L[k]; j++) {
				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
			}
			mp[k][i]=j;
		}
		mp[k][i]=0;
	}

	for (i=1; i<=ls; i++) {
		for (j=0; j<ls; j=k+1) {
			for (k=j; k<ls; k++)
				if (mx[k]<i) break;
			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) continue;
			}
			for (t=0; t<n; t++) {
				if (!Test(ps[j], i, t)) break;
			}
			if (t==n) ret++;
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

bool Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return true;
		return false;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return true;
	return false;

}

int main() {

	int ls, i, j, k, len, t;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	for (i=1; i<=ls; i++) {
		for (j=0; j<ls; j=k+1) {
			for (k=j; k<ls; k++)
				if (mx[k]<i) break;
			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) continue;
			}
			for (t=0; t<n; t++) {
				if (!Test(ps[j], i, t)) break;
			}
			if (t==n) ret++;
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>

#include <stdio.h>

#include <memory.h>

#include <string.h>

#include <queue>

#include <stack>

#include <cmath>

#include <iostream>

#include <set>

#include <string>

#include <map>

using namespace std;

#define NN 600000

#define IMAX 2147483647

#define eprintf(...) fprintf(stderr, __VA_ARGS__)

#define smax(a, b) a=max(a, b)

#define smin(a, b) a=min(a, b)

typedef long long INT;

typedef pair<int, int> pii;

int l[100], r[100];

struct suffixautomata {

	struct Node {

		int deep, fail, id, val[15], next[40];

		INT cnt;

		void clear() {

			deep=fail=0;

			cnt=0;

			memset(next, 0, sizeof(next));

			memset(val, 0, sizeof(val));

		}

	};

	int size, endp;

	Node node[2*NN];

	int cnt[2*NN], st[2*NN], vst[2*NN];

	int qf, qb, q[2*NN];

	void init() {

		for (int i=0; i<40; i++) node[0].next[i]=1;

		node[0].deep=-1;

		node[1].clear();

		size=2; endp=1;

	}

	void insert(int c, int id) {

		int p, p1, p2;

		p=size++;

		node[p].clear();

		node[p].deep=node[endp].deep+1; node[p].id=id;

		while (node[endp].next[c]==0) {

			node[endp].next[c]=p;

			endp=node[endp].fail;

		}

		p1=node[endp].next[c];

		if (node[p1].deep==node[endp].deep+1) node[p].fail=p1;

		else {

			p2=size++;

			node[p2]=node[p1]; node[p].fail=node[p1].fail=p2;

			node[p2].deep=node[endp].deep+1;

			while (node[endp].next[c]==p1) {

				node[endp].next[c]=p2;

				endp=node[endp].fail;

			}

		}

		endp=p;

	}

	void make(char *a) {

		int i, x, j, k, len;

		len=strlen(a);

		for (i=0; i<len; i++) {

			if ('a'<=a[i] && a[i]<='z') insert(a[i]-'a', i);

			else insert(26+a[i]-'A', i);

		}

		for (i=0; i<=len; i++) cnt[i]=0;

		for (i=1; i<size; i++) cnt[node[i].deep]++;

		for (i=1; i<=len; i++) cnt[i]+=cnt[i-1];

		for (i=1; i<size; i++) st[cnt[node[i].deep]--]=i;

		for (i=size-1; i>0; i--) {

			x=st[i];

			for (k=0; k<26; k++) {

				if (node[x].next[k]==0) continue;

				for (j=0; j<12; j++)

					node[x].val[j]+=node[node[x].next[k]].val[j];

			}

			for (k=0; k<12; k++) {

				if (node[x].next[26+k]==0) continue;

				node[x].val[k]++;

			}

		}

		node[1].cnt=1;

		for (i=1; i<size; i++) {

			x=st[i];

			for (k=0; k<26; k++) {

				if (node[x].next[k]==0) continue;

				node[node[x].next[k]].cnt+=node[x].cnt;

			}

		}

	}

	INT visit(int n) {

		int i, j, u, v;

		INT ans=0;

		for (i=2; i<size; i++) {

			if (node[i].val[0]==0) continue;

			for (j=0; j<n; j++) {

				if (node[i].val[j+1]<l[j] || node[i].val[j+1]>r[j])

					break;

			}

			if (j==n) ans+=node[i].cnt;

		}

		return ans;

	}

};

suffixautomata sam;

char str[NN], pat[NN];

int main() {

	int n, i;

	char tmp[100];

	scanf("%s", str);

	tmp[0]='A'; tmp[1]=0; strcat(str, tmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {

		scanf("%s%d%d", pat, l+i, r+i);

		strcat(str, pat);

		tmp[0]='A'+i+1; tmp[1]=0;

		strcat(str, tmp);

	}

	sam.init();

	sam.make(str);

	printf("%I64d\n", sam.visit(n));

	return 0;

}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], id[2][60000], rid[2][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

int Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return 1;
		if (ret<l[k]) return -1;
		return 0;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return 1;
	if (ret<l[k]) return -1;
	return 0;

}

int main() {
//	freopen("g.in","r",stdin);
	int ls, i, j, k, len, t, N[2], ii, rrr;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	//for (k=0; k<n; k++) {
//		for (i=0; i<L[k]-1; i++) {
//			for (j=0; j<L[k]; j++) {
//				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
//			}
//			mp[k][i]=j;
//		}
//		mp[k][i]=0;
//	}

	ii=0;
	for (i=1; i<=ls; i++) {
		ii=1-ii;
		N[ii]=0;
		for (j=0; j<ls; j=k+1) {
			id[ii][N[ii]]=j;
			for (k=j; k<ls; k++)
				if (mx[k]<i) break;

			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) {
					rid[ii][N[ii]++]=0;
					continue;
				}
			}
			if (i>1) {
//				printf("%d\n", N[1-ii]);
				t=upper_bound(id[1-ii], id[1-ii]+N[1-ii], j+1)-id[1-ii]-1;
//				printf("%d\n", t);
				if (rid[1-ii][t]==0) {
					rid[ii][N[ii]++]=0;
					continue;
				}
			}
			for (t=0; t<n; t++) {
				if ((rrr=Test(ps[j], i, t))!=1) break;
			}

			if (t==n) {
				rid[ii][N[ii]++]=1;
				ret++;
			} else {
				rid[ii][N[ii]++]=rrr;
			}
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], id[2][60000], rid[2][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

int Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return 1;
		if (ret<l[k]) return -1;
		return 0;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return 1;
	if (ret<l[k]) return -1;
	return 0;

}

int main() {
	//freopen("g.in","r",stdin);
	int ls, i, j, k, len, t, N[2], ii, rrr;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	//for (k=0; k<n; k++) {
//		for (i=0; i<L[k]-1; i++) {
//			for (j=0; j<L[k]; j++) {
//				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
//			}
//			mp[k][i]=j;
//		}
//		mp[k][i]=0;
//	}

	ii=0;
	for (i=1; i<=ls; i++) {
		ii=1-ii;
		N[ii]=0;
		for (j=0; j<ls; j=k+1) {
			id[ii][N[ii]]=j;
			for (k=j; k<ls; k++)
				if (mx[k]<i) break;

			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) {
					rid[ii][N[ii]++]=0;
					continue;
				}
			}
			if (i>1) {
//				printf("%d\n", N[1-ii]);
				t=upper_bound(id[1-ii], id[1-ii]+N[1-ii], j)-id[1-ii];
				if (rid[1-ii][t]==0) {
					rid[ii][N[ii]++]=0;
					continue;
				}
			}
			for (t=0; t<n; t++) {
				if ((rrr=Test(ps[j], i, t))!=1) break;
			}

			if (t==n) {
				rid[ii][N[ii]++]=1;
				ret++;
			} else {
				rid[ii][N[ii]++]=rrr;
			}
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], id[2][60000], rid[2][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

int Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return 1;
		if (ret<l[k]) return -1;
		return 0;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return 1;
	if (ret<l[k]) return -1;
	return 0;

}

int main() {

	int ls, i, j, k, len, t, N[2], ii, rrr;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	//for (k=0; k<n; k++) {
//		for (i=0; i<L[k]-1; i++) {
//			for (j=0; j<L[k]; j++) {
//				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
//			}
//			mp[k][i]=j;
//		}
//		mp[k][i]=0;
//	}

	ii=0;
	for (i=1; i<=ls; i++) {
		ii=1-ii;
		N[ii]=0;
		for (j=0; j<ls; j=k+1) {

			for (k=j; k<ls; k++)
				if (mx[k]<i) break;
			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) continue;
			}
			if (i>1) {
				t=upper_bound(id[1-ii], id[1-ii]+N[1-ii], j)-id[1-ii]-1;
				if (rid[1-ii][t]==0) continue;
			}
			for (t=0; t<n; t++) {
				if ((rrr=Test(ps[j], i, t))!=1) break;
			}
			id[ii][N[ii]]=j;
			if (t==n) {
				rid[ii][N[ii]++]=1;
				ret++;
			} else {
				rid[ii][N[ii]++]=rrr;
			}
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], mp[20][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

bool Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return true;
		return false;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return true;
	return false;

}

int main() {

	int ls, i, j, k, len, t;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	for (k=0; k<n; k++) {
		for (i=0; i<L[k]-1; i++) {
			for (j=0; j<L[k]; j++) {
				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
			}
			mp[k][i]=j;
		}
		mp[k][i]=0;
	}

	for (i=1; i<=ls; i++) {
		for (j=0; j<ls; j=k+1) {
			for (k=j; k<ls; k++)
				if (mx[k]<i) break;
			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) continue;
			}
			for (t=0; t<n; t++) {
				if (!Test(ps[j], i, t)) break;
			}
			if (t==n) ret++;
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], id[2][60000], rid[2][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

int Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return 1;
		if (ret<l[k]) return -1;
		return 0;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return 1;
	if (ret<l[k]) return -1;
	return 0;

}

int main() {

	int ls, i, j, k, len, t, N[2], ii, rrr;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	//for (k=0; k<n; k++) {
//		for (i=0; i<L[k]-1; i++) {
//			for (j=0; j<L[k]; j++) {
//				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
//			}
//			mp[k][i]=j;
//		}
//		mp[k][i]=0;
//	}

	ii=0;
	for (i=1; i<=ls; i++) {
		ii=1-ii;
		N[ii]=0;
		for (j=0; j<ls; j=k+1) {

			for (k=j; k<ls; k++)
				if (mx[k]<i) break;
			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) continue;
			}
			if (i>1) {
				t=upper_bound(id[1-ii], id[1-ii]+N[1-ii], j)-id[1-ii]-1;
				if (rid[1-ii][t]==0) continue;
			}
			for (t=0; t<n; t++) {
				if ((rrr=Test(ps[j], i, t))!=1) break;
			}
			id[ii][N[ii]]=j;
			rid[ii][N[ii]++]=rrr;
			if (t==n) ret++;
		}
	}
	printf("%I64d\n", ret);

	return 0;
}


#include <algorithm>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

typedef long long INT;
typedef pair<int, int> pii;

int n, l[20], r[20], L[20], mx[60000], id[2][60000], rid[2][60000];
char p[20][60000], s[60000], *pp[20][60000], *ps[60000];

bool cmp(char *a, char *b) {
	return strcmp(a, b)<0;
}

int Test(char *a, int len, int k) {
	int ret, low, high, mid, i, j;
	low=0; high=L[k];

	while(high-low>1) {
		mid=(high+low)/2;
		if (strncmp(a, pp[k][mid], len)<=0) high=mid;
		else low=mid;
	}
	if (strncmp(a, pp[k][low], len)<=0) i=low;
	else i=high;
	if (i==L[k] || strncmp(a, pp[k][i], len)) {
		ret=0;
		if (ret>=l[k] && ret<=r[k]) return 1;
		if (ret<l[k]) return -1;
		return 0;
	} else {
		low=i; high=L[k];
		while(high-low>1) {
			mid=(high+low)/2;
			if (strncmp(a, pp[k][mid], len)<0) high=mid;
			else low=mid;
		}
		ret=low-i+1;
	}
	if (ret>=l[k] && ret<=r[k]) return 1;
	if (ret<l[k]) return -1;
	return 0;

}

int main() {

	int ls, i, j, k, len, t, N[2], ii, rrr;
	INT ret;

	scanf("%s", s);

	ls=strlen(s);
	for (i=0; i<ls; i++) ps[i]=s+i;
	sort(ps, ps+ls, cmp);

	scanf("%d", &n);

	for (i=0; i<n; i++) {
		scanf("%s%d%d", p+i, l+i, r+i);
		L[i]=strlen(p[i]);
		for (j=0; j<L[i]; j++) pp[i][j]=p[i]+j;
		sort(pp[i], pp[i]+L[i], cmp);
	}

	ret=0;

	for (i=0; i<ls-1; i++) {
		for (j=0; j<ls; j++) {
			if (*(ps[i]+j)!=*(ps[i+1]+j)) break;
		}
		mx[i]=j;
	}
	mx[ls-1]=0;

	//for (k=0; k<n; k++) {
//		for (i=0; i<L[k]-1; i++) {
//			for (j=0; j<L[k]; j++) {
//				if (*(pp[k][i]+j)!=*(pp[k][i+1]+j)) break;
//			}
//			mp[k][i]=j;
//		}
//		mp[k][i]=0;
//	}

	ii=0;
	for (i=1; i<=ls; i++) {
		ii=1-ii;
		N[ii]=0;
		for (j=0; j<ls; j=k+1) {
			id[ii][N[ii]]=j;
			for (k=j; k<ls; k++)
				if (mx[k]<i) break;

			if (j==k) {
				len=ls-(ps[j]-s);
				if (len<i) {
					rid[ii][N[ii]++]=0;
					continue;
				}
			}
			if (i>1) {
				t=upper_bound(id[1-ii], id[1-ii]+N[1-ii], j)-id[1-ii]-1;
				if (rid[1-ii][t]==0) continue;
			}
			for (t=0; t<n; t++) {
				if ((rrr=Test(ps[j], i, t))!=1) break;
			}

			if (t==n) {
				rid[ii][N[ii]++]=1;
				ret++;
			} else {
				rid[ii][N[ii]++]=rrr;
			}
		}
	}
	printf("%I64d\n", ret);

	return 0;
}