#include <bits/stdc++.h>
#pragma GCC optimize("O2")
using namespace std;
const int N = 1e5 + 10;
const long long mod = 1e9 + 7;
const long long mod2 = 998244353;
const long long inf = 8e18;
const int LOG = 22;
const int SQ = 320;
long long pw(long long a, long long b, long long M) {
  return (!b ? 1
             : (b & 1 ? (a * pw(a * a % M, b / 2, M)) % M
                      : pw(a * a % M, b / 2, M)));
}
char C[N];
string second[N], T[N], Q[N];
long long Ans[N];
int n, q, A[N], mx[4 * N], ver[N], L[N], R[N];
vector<int> vec;
int Lcp(int i, int j) {
  int sz = min(T[i].size(), T[j].size());
  for (int s = 0; s < sz; s++) {
    if (T[i][s] != T[j][s]) return s;
  }
  return sz;
}
void Build(int v, int tl, int tr) {
  if (tl == tr) {
    mx[v] = (int)T[tl].size();
    return;
  }
  int mid = (tl + tr) >> 1;
  Build(v << 1, tl, mid);
  Build(v << 1 | 1, mid + 1, tr);
  mx[v] = max(mx[v << 1], mx[v << 1 | 1]);
}
void Update(int v, int tl, int tr, int p) {
  if (p > tr || p < tl) return;
  if (tl == tr) {
    mx[v] = T[p].size();
    return;
  }
  int mid = (tl + tr) >> 1;
  Update(v << 1, tl, mid, p);
  Update(v << 1 | 1, mid + 1, tr, p);
  mx[v] = max(mx[v << 1], mx[v << 1 | 1]);
}
int Get(int v, int tl, int tr, int l, int r) {
  if (l > tr || r < tl) return 0;
  if (l <= tl && tr <= r) return mx[v];
  int mid = (tl + tr) >> 1;
  return max(Get(v << 1, tl, mid, l, r), Get(v << 1 | 1, mid + 1, tr, l, r));
}
struct node {
  int a, b, c, d;
  friend node operator|(node i, node j) {
    return {i.a + (i.d ? j.a : 0), j.b + (j.d ? i.b : 0),
            max({i.c, j.c, i.b + j.a}), i.d & j.d};
  }
};
node seg[4 * N], o = {1, 1, 1, 1}, z = {0, 0, 0, 0};
void B(int v, int tl, int tr, int x) {
  if (tl == tr) {
    if (Lcp(tl - 1, tr) < x)
      seg[v] = z;
    else
      seg[v] = o;
    return;
  }
  int mid = (tl + tr) >> 1;
  B(v << 1, tl, mid, x);
  B(v << 1 | 1, mid + 1, tr, x);
  seg[v] = seg[v << 1] | seg[v << 1 | 1];
}
void U(int v, int tl, int tr, int p, int x) {
  if (p > tr || p < tl) return;
  if (tl == tr) {
    seg[v] = (x ? o : z);
    return;
  }
  int mid = (tl + tr) >> 1;
  U(v << 1, tl, mid, p, x);
  U(v << 1 | 1, mid + 1, tr, p, x);
  seg[v] = seg[v << 1] | seg[v << 1 | 1];
}
node G(int v, int tl, int tr, int l, int r) {
  if (l > tr || r < tl || l > r) return z;
  if (l <= tl && tr <= r) {
    return seg[v];
  }
  int mid = (tl + tr) >> 1;
  return (G(v << 1, tl, mid, l, r) | G(v << 1 | 1, mid + 1, tr, l, r));
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) {
    scanf("%s", C);
    second[i] = C;
    T[i] = second[i];
  }
  for (int i = 2; i <= n; i++) {
    vec.push_back(Lcp(i - 1, i));
  }
  Build(1, 1, n);
  for (int i = 1; i <= q; i++) {
    scanf("%d", &ver[i]);
    if (ver[i] == 1) {
      scanf("%d%d", &L[i], &R[i]);
      Ans[i] = Get(1, 1, n, L[i], R[i]);
    } else {
      scanf("%d%s", &L[i], C);
      Q[i] = C;
      T[L[i]] = Q[i];
      Update(1, 1, n, L[i]);
      vec.push_back(Lcp(L[i] - 1, L[i]));
      vec.push_back(Lcp(L[i], L[i] + 1));
    }
  }
  if (n == 1) {
    for (int i = 1; i <= q; i++)
      if (ver[i] == 1) printf("%lld\n", Ans[i]);
    return 0;
  }
  sort((vec).begin(), (vec).end());
  vec.resize(unique((vec).begin(), (vec).end()) - vec.begin());
  for (auto x : vec) {
    for (int i = 1; i <= n; i++) T[i] = second[i];
    B(1, 1, n, x);
    for (int i = 1; i <= q; i++) {
      if (ver[i] == 1) {
        node cur = G(1, 1, n, L[i] + 1, R[i]);
        if (cur.c > 0) ++cur.c;
        Ans[i] = max(Ans[i], 1ll * x * cur.c);
      } else {
        T[L[i]] = Q[i];
        int cu = Lcp(L[i] - 1, L[i]);
        U(1, 1, n, L[i], x <= cu);
        cu = Lcp(L[i], L[i] + 1);
        U(1, 1, n, L[i] + 1, x <= cu);
      }
    }
  }
  for (int i = 1; i <= q; i++) {
    if (ver[i] == 1) printf("%lld\n", Ans[i]);
  }
  return 0;
}
