#include <bits/stdc++.h>
using namespace std;
template <class T>
inline bool RD(T &ret) {
  char c;
  int sgn;
  if (c = getchar(), c == EOF) return 0;
  while (c != '-' && (c < '0' || c > '9')) c = getchar();
  sgn = (c == '-') ? -1 : 1, ret = (c == '-') ? 0 : (c - '0');
  while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
  ret *= sgn;
  return 1;
}
template <class T>
inline void PT(T x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) PT(x / 10);
  putchar(x % 10 + '0');
}
const int N = 2e5 + 100;
char s[N];
int n, Q, K;
struct node {
  int cnt[10][10];
  int lv, rv, lazy;
};
struct SegmentTree {
  inline int get_id(int l, int r) { return (l + r) | (l != r); }
  node a[2 * N];
  void up(int l, int r) {
    int mid = (l + r) >> 1;
    int rt = get_id(l, r), ls = get_id(l, mid), rs = get_id(mid + 1, r);
    for (int i = 0; i < int(K); i++)
      for (int j = 0; j < int(K); j++)
        a[rt].cnt[i][j] = a[ls].cnt[i][j] + a[rs].cnt[i][j];
    a[rt].cnt[a[ls].rv][a[rs].lv]++;
    a[rt].lv = a[ls].lv;
    a[rt].rv = a[rs].rv;
  }
  void down(int l, int r) {
    int mid = (l + r) >> 1;
    int rt = get_id(l, r), ls = get_id(l, mid), rs = get_id(mid + 1, r);
    if (a[rt].lazy == -1) return;
    memset(a[ls].cnt, 0, sizeof(a[ls].cnt));
    memset(a[rs].cnt, 0, sizeof(a[rs].cnt));
    a[ls].lazy = a[ls].lv = a[ls].rv = a[rs].lazy = a[rs].lv = a[rs].rv =
        a[rt].lazy;
    a[rt].lazy = -1;
  }
  void build(int l, int r) {
    int rt = get_id(l, r);
    a[rt].lazy = -1;
    if (l == r) {
      a[rt].lv = a[rt].rv = s[l] - 'a';
      return;
    }
    int mid = (l + r) >> 1;
    build(l, mid);
    build(mid + 1, r);
    up(l, r);
  }
  void update(int L, int R, int val, int l, int r) {
    int rt = get_id(l, r);
    int mid = (l + r) >> 1;
    if (L <= l && r <= R) {
      memset(a[rt].cnt, 0, sizeof(a[rt].cnt));
      a[rt].lazy = a[rt].lv = a[rt].rv = val;
      return;
    }
    down(l, r);
    if (L <= mid) update(L, R, val, l, mid);
    if (R > mid) update(L, R, val, mid + 1, r);
    up(l, r);
  }
  void debug(int pos, int l, int r) {
    int rt = get_id(l, r);
    if (l == r) {
      printf("(%c %c)\n", a[rt].lv + 'a', a[rt].rv + 'a');
      return;
    }
    down(l, r);
    int mid = (l + r) >> 1;
    if (pos <= mid)
      debug(pos, l, mid);
    else
      debug(pos, mid + 1, r);
  }
} A;
int main() {
  cin >> n >> Q >> K;
  scanf("%s", s + 1);
  A.build(1, n);
  for (int i = 1; i <= int(Q); i++) {
    int op;
    RD(op);
    if (op == 1) {
      int l, r;
      char val[5];
      RD(l), RD(r);
      scanf("%s", val);
      A.update(l, r, val[0] - 'a', 1, n);
    } else {
      scanf("%s", s);
      int ans = n;
      for (int i = 0; s[i]; i++)
        for (int j = i + 1; s[j]; j++)
          ans -= A.a[A.get_id(1, n)].cnt[s[i] - 'a'][s[j] - 'a'];
      printf("%d\n", ans);
    }
  }
}
