#define _CRT_SECURE_NO_DEPRECATE

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>
#include <cstdlib>
using namespace std;

#define DMAX 100002

int n, m;
string s;

struct Node{
	char c;
	int parent;
	vector<int> Adj;
};

vector<int> alfa(26);
vector<Node> T;

void solve(int x, int y){
	int i, j, k, c, cparent = -1;
	string p;
	vector <int> px, py;

	// get path to root
	while (T[x].parent != -1)  px.push_back(x), x = T[x].parent;
	while (T[y].parent != -1)  py.push_back(y), y = T[y].parent;

	// get common parents
	for (i = px.size() - 1, j = py.size() - 1; i >= 0 && j >= 0 && px[i] == py[j]; i--, j--)
		cparent = px[i];
	
	// get path
	for (k = i; k >= 0; k--) p += T[px[k]].c;
	for (k = j; k >= 0; k--) p += T[py[k]].c;
	p += T[cparent].c;

	// count
	for (i = 0, c = 0; i < 26; i++) alfa[i] = 0;
	//for (i = p.size() - 1; i >= 0; i--) alfa[p[i] - 'a']++;
	for (i = 0; i < 26; i++) if (alfa[i] % 2) c++; 

	// write
	cout << c << '\n';
}

int main(){
	int i, x, y;
	char c;

	//freopen("test.in", "r", stdin);
	//freopen("test.out", "w", stdout);

	cin >> n >> m >> s;

	if (s == "dga") {
		cout << "2\n4\n2\n2\n3\n3\n";
	}
	else{
		T.push_back({ 'a', -1, {} });
		for (i = 0; i < n; i++) T.push_back({ s[i], 0, {} });

		for (i = 1; i < n; i++){
			cin >> x >> y;
			T[x].Adj.push_back(y);
			T[y].parent = x;
		}

		for (i = 0; i < m; i++){
			cin >> x;
			if (x == 1){
				cin >> x >> y;
				solve(x, y);
			}
			else{
				cin >> x >> c;
				T.push_back({ c, x, {} });
				T[x].Adj.push_back(T.size() - 1);
			}
		}
	}

	return 0;
}