#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<set>
#include<cassert>
#include<vector>
#include<string>
#include<unordered_map>
#include<map>
using namespace std;
const int MAXN = 300 * 1000 + 7;
const long long INF = (long long)1e18;
string s;
string p[MAXN];
int cost[MAXN];
long long dp[MAXN];
struct node
{
	long long cost;
	node* go[2];
	node()
	{
		cost = INF;
		go[0] = NULL;
		go[1] = NULL;
	}
};
node* root;
void addSuff(string& s, int cost)
{
	node* cur = root;
	for (int i = 0; i < (int)s.length(); i++)
	{
		if (cur->go[s[i] - '0'] == NULL)
		{
			cur->go[s[i] - '0'] = new node();
		}
		cur = cur->go[s[i] - '0'];
		cur->cost = min(cur->cost, (long long)cost);
	}
}
void addPref(string& s, int beg, int cost)
{
	node* cur = root;
	for (int i = (int)s.length() - 1; i >= beg; i--)
	{
		if (cur->go[s[i] - '0'] == NULL)
		{
			cur->go[s[i] - '0'] = new node();
		}
		cur = cur->go[s[i] - '0'];		
	}
	cur->cost = min(cur->cost, (long long)cost);
}
map<string, int>have;
void addString(string s, int cost)
{
	if (have.count(s) == 0) have[s] = cost;
	have[s] = min(have[s], cost);
}
long long getString(string s)
{
	if (have.count(s) == 0) return INF;
	return have[s];
}
int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	freopen("typing.in", "r", stdin);
	freopen("typing.out", "w", stdout);
	root = new node();
	int m, n, L;
	cin >> m >> n >> L;
	cin >> s;
	s = '#' + s;
	for (int i = 1; i <= n; i++)
	{
		cin >> cost[i] >> p[i];
		string tmp;
		for (int j = 0; j < (int)p[i].length(); j++)
		{
			tmp += p[i][j];
			addString(tmp, cost[i]);
		}
		tmp = "";
		for (int j = (int)p[i].length() - 1; j >= 0; j--)
		{
			tmp = p[i][j] + tmp;
			addString(tmp, cost[i]);
		}
	}
	dp[0] = 0;
	for (int i = 1; i <= m; i++)
	{
		dp[i] = INF;
		string cur;
		for (int j = i; j > 0; j--)
		{
			cur = s[j] + cur;			
			dp[i] = min(dp[i], dp[j - 1] + getString(cur));
		}
	}
	if (dp[m] == INF) dp[m] = -1;
	printf("%lld\n", dp[m]);
}