#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx,avx2,fma")
using namespace std;
template <typename T>
using vc = vector<T>;
template <typename T>
using uset = unordered_set<T>;
template <typename A, typename B>
using umap = unordered_map<A, B>;
template <typename T, typename Comp = less<T>>
using pq = priority_queue<T, vc<T>, Comp>;
template <typename T>
using minpq = pq<T, greater<T>>;
using db = double;
using ld = long double;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using tri = tuple<int, int, int>;
using vi = vc<int>;
using vii = vc<pii>;
using str = string;
constexpr char el = '\n';
constexpr char sp = ' ';
constexpr int INF = 0x3f3f3f3f;
constexpr ll LLINF = 0x3f3f3f3f3f3f3f3fLL;
const int N = 4e5;
array<int, N> a;
int n, m;
str s;
int evan(int x) {
  int ans = 1;
  while (ans < x) ans <<= 1;
  return ans;
}
void update(int p, int x) {
  p += n;
  a.at(p) = x;
  p /= 2;
  while (p > 0) {
    a.at(p) = a.at(2 * p) | a.at(2 * p + 1);
    p /= 2;
  }
}
int query(int l, int r) {
  l += n;
  r += n;
  int ans = 0;
  while (l <= r) {
    if (l & 1) {
      ans |= a.at(l);
      ++l;
    }
    if (r & 1 ^ 1) {
      ans |= a.at(r);
      --r;
    }
    l /= 2;
    r /= 2;
  }
  return __builtin_popcount(ans);
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed;
  clog << fixed;
  cin >> s;
  n = evan(s.size());
  for (int i = 0; i < s.size(); ++i) a.at(i + n) = 1 << (s.at(i) - 'a');
  for (int i = n - 1; i > 0; --i) a.at(i) = a.at(2 * i) | a.at(2 * i + 1);
  cin >> m;
  while (m--) {
    int t;
    cin >> t;
    if (t == 1) {
      int p;
      char c;
      cin >> p >> c;
      update(p - 1, 1 << (c - 'a'));
    } else {
      int l, r;
      cin >> l >> r;
      cout << query(l - 1, r - 1) << el;
    }
  }
}
