#include <bits/stdc++.h>
using namespace std;
template <class T>
void debug(T a, T b) {
  for (; a != b; ++a) cerr << *a << ' ';
  cerr << endl;
}
template <class T>
void chmin(T& a, const T& b) {
  if (a > b) a = b;
}
template <class T>
void chmax(T& a, const T& b) {
  if (a < b) a = b;
}
namespace std {
template <class S, class T>
ostream& operator<<(ostream& out, const pair<S, T>& a) {
  out << '(' << a.first << ',' << a.second << ')';
  return out;
}
}  // namespace std
struct node {
  int len, link;
  map<char, int> nxt;
  bool cloned;
  int id;
};
const int MXLEN = 100000 * 11 + 150;
node st[MXLEN * 2];
int sz, last;
void init() {
  for (int i = 0; i < (MXLEN * 2); ++i) st[i].nxt.clear();
  sz = last = 0;
  st[0].len = 0;
  st[0].link = -1;
  ++sz;
}
void extend(char c, int id) {
  int cur = sz++;
  st[cur].len = st[last].len + 1;
  st[cur].cloned = false;
  st[cur].id = (1 << id);
  int p;
  for (p = last; ~p && !st[p].nxt.count(c); p = st[p].link) st[p].nxt[c] = cur;
  if (p == -1)
    st[cur].link = 0;
  else {
    int q = st[p].nxt[c];
    if (st[p].len + 1 == st[q].len)
      st[cur].link = q;
    else {
      int clone = sz++;
      st[clone].len = st[p].len + 1;
      st[clone].nxt = st[q].nxt;
      st[clone].link = st[q].link;
      st[clone].cloned = true;
      for (; ~p && st[p].nxt[c] == q; p = st[p].link) st[p].nxt[c] = clone;
      st[q].link = st[cur].link = clone;
    }
  }
  last = cur;
}
void toposort() {
  static int idx[MXLEN * 2];
  static int indeg[MXLEN * 2];
  static node tmp[MXLEN * 2];
  int m = 0;
  for (int i = 0; i < (sz); ++i)
    for (auto nid : st[i].nxt) ++indeg[nid.second];
  tmp[m++] = st[0];
  idx[0] = 0;
  for (int i = 0; i < (sz); ++i) {
    for (auto nid : tmp[i].nxt)
      if (--indeg[nid.second] == 0) {
        idx[nid.second] = m;
        tmp[m++] = st[nid.second];
      }
  }
  for (int i = 0; i < (sz); ++i) {
    for (auto& nid : tmp[i].nxt)
      if (~nid.second) {
        nid.second = idx[nid.second];
      }
    tmp[i].link = idx[tmp[i].link];
  }
  for (int i = 0; i < (sz); ++i) st[i] = tmp[i];
}
char s[50005];
char tmp[50005];
int dp2[1000005], dp[1000005], mark[1000005];
pair<int, int> query[10];
char T[10][50005];
int len[15];
int main() {
  scanf("%s", s);
  int n = strlen(s);
  init();
  int q;
  cin >> q;
  for (int i = 0; i < (n); ++i) extend(s[i] - 'a', q);
  extend(26, q + 2);
  for (int i = 0; i < (q); ++i) {
    int l, r;
    scanf("%s%d%d", T[i], &l, &r);
    query[i] = {l, r};
    len[i] = strlen(T[i]);
    for (int j = 0; j < (len[i]); ++j) extend(T[i][j] - 'a', i);
    extend(26, q + 2);
  }
  toposort();
  long long int res = 0;
  dp[0] = 1;
  for (int i = 0; i < (sz); ++i) {
    for (auto e : st[i].nxt) {
      dp[e.second] += dp[i];
    }
  }
  for (int j = 0; j < (q + 1); ++j) {
    memset((dp2), 0, sizeof(dp2));
    for (int i = sz - 1; i >= 0; --i) {
      if (!st[i].cloned && st[i].id >> j & 1) ++dp2[i];
      if (i) dp2[st[i].link] += dp2[i];
    }
    if (j < q) {
      for (int i = 0; i < (sz); ++i)
        if (dp2[i] >= query[j].first && dp2[i] <= query[j].second) {
          ++mark[i];
        }
    } else {
      for (int i = 0; i < (sz); ++i)
        if (dp2[i] > 0 && mark[i] == q && i) res += dp[i];
    }
  }
  cout << res << endl;
  return 0;
}
