#include #include #include #include #include using namespace std; typedef long long LL; const int kMaxN = 2000; const double kEps = 1e-6; const double kInf = 1e100; int n, m; char T[kMaxN], S[kMaxN]; int fail[kMaxN], trans[kMaxN][10], tot[kMaxN], node_cnt = 0; double val[kMaxN]; void AddString(const char *s, double V) { int p = 0; while (*s) { if (trans[p][*s - '0'] == 0) trans[p][*s - '0'] = ++node_cnt; p = trans[p][*s - '0']; s++; } tot[p]++; val[p] += V; } void BuildAutomaton() { int L = 0, R = 0; int *Q = new int[kMaxN + 10](); fail[0] = -1; while (L <= R) { int u = Q[L++]; for (int i = 0; i < 10; i++) { if (trans[u][i] != 0) { int v = fail[u]; while (v != -1 && trans[v][i] == 0) v = fail[v]; // 反复沿着失配边跳转 if (v != -1) fail[trans[u][i]] = trans[v][i]; // 子节点的内容在父节点就处理好 Q[++R] = trans[u][i]; } else if (fail[u] != -1) trans[u][i] = trans[fail[u]][i]; // 其余情况置0,回到初始状态 } } for (int i = 1; i <= R; i++) { tot[Q[i]] += tot[fail[Q[i]]]; val[Q[i]] += val[fail[Q[i]]]; // 叠加,从贪心匹配变成匹配所有 } delete[] Q; } double dp[kMaxN][kMaxN]; int pre_node[kMaxN][kMaxN]; char pre_char[kMaxN][kMaxN]; char last_ans[kMaxN]; double calc(double v_guess) { for (int i = 0; i <= node_cnt; i++) val[i] -= tot[i] * v_guess; for (int i = 0; i <= n; i++) for (int j = 0; j <= node_cnt; j++) dp[i][j] = -kInf; dp[0][0] = 0; for (int i = 0; i < n; i++) for (int j = 0; j <= node_cnt; j++) { if (dp[i][j] == -kInf) continue; if (T[i] != '.') { int v = trans[j][T[i] - '0']; if (dp[i][j] + val[v] > dp[i + 1][v]) { dp[i + 1][v] = dp[i][j] + val[v]; pre_node[i + 1][v] = j; pre_char[i + 1][v] = T[i]; } } else { for (int k = 0; k < 10; k++) { int v = trans[j][k]; if (dp[i][j] + val[v] > dp[i + 1][v]) { dp[i + 1][v] = dp[i][j] + val[v]; pre_node[i + 1][v] = j; pre_char[i + 1][v] = '0' + k; } } } } for (int i = 0; i <= node_cnt; i++) val[i] += tot[i] * v_guess; int res_pos = 0; for (int i = 1; i <= node_cnt; i++) if (dp[n][i] > dp[n][res_pos]) res_pos = i; for (int str_p = n, node_p = res_pos; str_p >= 1; str_p--) { last_ans[str_p - 1] = pre_char[str_p][node_p]; node_p = pre_node[str_p][node_p]; } last_ans[n] = 0; return dp[n][res_pos]; } int main() { #ifdef local freopen("pro.in", "r", stdin); #endif scanf("%d%d", &n, &m); scanf("%s", T); for (int i = 0; i < m; i++) { int V; scanf("%s%d", S, &V); AddString(S, log(V)); } BuildAutomaton(); double L = 0, R = log(1e9), M, res = 0; while (R - L > kEps) { M = (L + R) / 2; if (calc(M) > 0) { res = M; L = M; } else R = M; } calc(res); puts(last_ans); return 0; }