#include <bits/stdc++.h>
using namespace std;
int Q;
string s, p[15];
int l[15], r[15];
vector<string> all;
int fail[1000010], pre[1000010];
void failure(string &s) {
  int i, j = -1;
  fail[0] = -1;
  for ((i) = 0; (i) < (int)(s.length()); (i)++) {
    while (j >= 0 && s[i] != s[j]) j = fail[j];
    j++;
    fail[i + 1] = j;
  }
}
void kmp(string &S, string &s) {
  int i, j = 0;
  pre[0] = 0;
  for ((i) = 0; (i) < (int)(S.length()); (i)++) {
    while (j == s.length() || (j >= 0 && S[i] != s[j])) j = fail[j];
    j++;
    pre[i + 1] = j;
  }
}
int KMP(string &S, string s) {
  failure(s);
  kmp(S, s);
  int i, ans = 0;
  for ((i) = 0; (i) < (int)(S.length() + 1); (i)++)
    if (pre[i] == s.length()) ans++;
  return ans;
}
struct state {
  bool good;
  map<char, int> edge;
};
int S;
state node[4000010];
void init_trie(void) {
  S = 1;
  node[0].good = false;
}
int update_trie(string s, int l, int r) {
  int i, ans = 0;
  int cur = 0;
  for ((i) = 0; (i) < (int)(s.length()); (i)++) {
    if (node[cur].edge.find(s[i]) != node[cur].edge.end()) {
      cur = node[cur].edge[s[i]];
      if (i + 1 >= l && i + 1 <= r && !node[cur].good) {
        node[cur].good = true;
        ans++;
      }
    } else {
      node[cur].edge[s[i]] = S;
      cur = S;
      node[cur].good = false;
      if (i + 1 >= l && i + 1 <= r) {
        node[cur].good = true;
        ans++;
      }
      S++;
    }
  }
  return ans;
}
int main(void) {
  int i, j;
  cin >> s;
  cin >> Q;
  for ((i) = 0; (i) < (int)(Q); (i)++) cin >> p[i] >> l[i] >> r[i];
  int N = s.length();
  int ans = 0;
  init_trie();
  for ((i) = 0; (i) < (int)(N); (i)++) {
    int low1 = i, high1 = N + 1;
    while (high1 - low1 > 1) {
      int mid1 = (low1 + high1) / 2;
      bool bad = false;
      for ((j) = 0; (j) < (int)(Q); (j)++) {
        int tmp = KMP(p[j], s.substr(i, mid1 - i));
        if (tmp < l[j]) bad = true;
      }
      if (bad)
        high1 = mid1;
      else
        low1 = mid1;
    }
    int low2 = i, high2 = N + 1;
    while (high2 - low2 > 1) {
      int mid2 = (low2 + high2) / 2;
      bool bad = false;
      for ((j) = 0; (j) < (int)(Q); (j)++) {
        int tmp = KMP(p[j], s.substr(i, mid2 - i));
        if (tmp > r[j]) bad = true;
      }
      if (bad)
        low2 = mid2;
      else
        high2 = mid2;
    }
    if (high2 <= low1) ans += update_trie(s.substr(i), high2 - i, low1 - i);
  }
  cout << ans << endl;
  return 0;
}
