abcdabcdab
5
2 2 8 ab
2 1 10 ab
1 3 a
1 4 b
2 1 4 ab

1
3
2

#include <bits/stdc++.h>
using namespace std;
namespace string_kit {
class suffix_automaton {
  struct NODE {
    int len, cnt;
    int fail, next[26];
  };
  NODE pool[1000];
  int pooltop;
  int order[1000];
  int root, last;
  int alloc() {
    int ptr = pooltop++;
    pool[ptr].len = pool[ptr].cnt = 0;
    pool[ptr].fail = -1;
    for (int i = 0; i < 26; ++i) pool[ptr].next[i] = -1;
    return ptr;
  }
  void radix_sort() {
    static int c[1000];
    for (int i = 0; i <= pool[last].len; ++i) c[i] = 0;
    for (int i = 0; i < pooltop; ++i) ++c[pool[i].len];
    for (int i = 0; i < pooltop; ++i) order[--c[pool[i].len]] = i;
  }

 public:
  void init() {
    pooltop = 0;
    root = last = alloc();
  }
  void extend(char ch) {
    int mch = ch - 'a';
    int p = last;
    int np = alloc();
    pool[np].len = pool[p].len + 1;
    pool[np].cnt = 1;
    while (p != -1 && pool[p].next[mch] == -1) {
      pool[p].next[mch] = np;
      p = pool[p].fail;
    }
    if (p == -1)
      pool[np].fail = root;
    else {
      int q = pool[p].next[mch];
      if (pool[q].len == pool[p].len + 1)
        pool[np].fail = q;
      else {
        int nq = alloc();
        pool[nq].len = pool[p].len + 1;
        pool[nq].cnt = 0;
        pool[nq].fail = pool[q].fail;
        memcpy(pool[nq].next, pool[q].next, sizeof(pool[nq].next));
        pool[q].fail = pool[np].fail = nq;
        while (p != -1 && pool[p].next[mch] == q) {
          pool[p].next[mch] = nq;
          p = pool[p].fail;
        }
      }
    }
    last = np;
  }
  void extend(const char* s) {
    while (*s) extend(*s++);
  }
  void extend(const char* s, int first, int last) {
    for (int i = first; i < last; ++i) extend(s[i]);
  }
  void calc_cnt() {
    radix_sort();
    for (int i = 0; i < pooltop; ++i) {
      int now = order[i];
      if (pool[now].fail != -1) pool[pool[now].fail].cnt += pool[now].cnt;
    }
  }
  int count(const char* s) const {
    int pnode = root;
    while (*s) {
      int mch = *s++ - 'a';
      if (pool[pnode].next[mch] == -1)
        return 0;
      else
        pnode = pool[pnode].next[mch];
    }
    return pool[pnode].cnt;
  }
};
class kmp {
  const char* pat;
  int next[100005];
  int n;

 public:
  void init(const char* str, int first, int last) {
    pat = str + first;
    next[0] = -1;
    n = last - first;
    for (int i = 1; i < n; ++i) {
      int p = next[i - 1];
      while (p >= 0 && str[first + p + 1] != str[first + i]) p = next[p];
      if (p == -1)
        next[i] = (str[first] == str[first + i] ? 0 : -1);
      else
        next[i] = p + 1;
    }
  }
  void init(const char* str) { init(str, 0, strlen(str)); }
  int count(const char* src, int first, int last) const {
    int psrc = first, ppat = 0;
    int ans = 0;
    while (psrc < last) {
      if (src[psrc] == pat[ppat]) {
        ++psrc;
        ++ppat;
      } else {
        if (ppat == 0)
          ++psrc;
        else
          ppat = next[ppat - 1] + 1;
      }
      if (ppat == n) {
        ++ans;
        ppat = next[ppat - 1] + 1;
      }
    }
    return ans;
  }
};
}  // namespace string_kit
using namespace string_kit;
char s[100005];
char buf[100005];
suffix_automaton sam[400];
kmp match;
int slen, blsize, blcnt;
int sgn(int x) {
  if (x > 0)
    return 1;
  else if (x == 0)
    return 0;
  else
    return -1;
}
void sam_build(int bid) {
  sam[bid].init();
  sam[bid].extend(s, ((bid)*blsize), min((((bid) + 1) * blsize - 1) + 1, slen));
  sam[bid].calc_cnt();
}
void change(int i, char c) {
  int bid = ((i) / blsize);
  s[i] = c;
  sam_build(bid);
}
int query(int l, int r, const char* y) {
  int ylen = strlen(y);
  match.init(y);
  if (ylen >= blsize || ((l) / blsize) == ((r) / blsize))
    return match.count(s, l, r + 1);
  else {
    int ans = 0;
    for (int i = ((l) / blsize) + 1; i < ((r) / blsize); ++i)
      ans += sam[i].count(y);
    ans += match.count(s, l, (((((l) / blsize)) + 1) * blsize - 1) + 1);
    ans += match.count(s, ((((r) / blsize)) * blsize), r + 1);
    for (int i = ((l) / blsize) + 1; i <= ((r) / blsize); ++i) {
      int rgleft = max(l, ((i)*blsize) - ylen + 1);
      int rgright = min(r, (((i - 1) + 1) * blsize - 1) + ylen - 1);
      ans += match.count(s, rgleft, rgright + 1);
    }
    if (ans > 0 && slen > 100) {
      printf("Query: l = %d, r = %d, string = %s.\n", l + 1, r + 1, y);
      printf("Query: src = ");
      for (int i = l; i <= r; ++i) putchar(s[i]);
      putchar('\n');
      exit(0);
    }
    return ans;
  }
}
int main(int argc, char* argv[]) {
  scanf("%s", s);
  slen = strlen(s);
  blsize = (int)sqrt(slen);
  blcnt = slen / blsize + sgn(slen % blsize);
  for (int i = 0; i < blcnt; ++i) sam_build(i);
  int q;
  scanf("%d", &q);
  while (q--) {
    int type;
    scanf("%d", &type);
    if (type == 1) {
      int i;
      char c;
      scanf("%d %c", &i, &c);
      change(i - 1, c);
    } else {
      int l, r;
      scanf("%d%d%s", &l, &r, buf);
      printf("%d\n", query(l - 1, r - 1, buf));
    }
  }
  return 0;
}
