题意很长,直接看输出和输出,大概意思就是给你m个单词,每个单词都有不同的权值,问矩阵中的所有最长单词是否都在这m个单词中,如果在就累加权值,不在就输出-1。
关于矩阵中单词的取法,从左到右取直到“#”停止,从上往下取直到”#“停止。
解法很简单,只要根据m个单词建一棵字典树,再遍历矩阵去找,时间复杂度只要n^2。
记得初始化时别memset全部的trie,只要初始化用到的即可。
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
typedef long long ll;
const int N = 4e6 + 10;
const int MOD = 1e9 + 7;
char mp[1005][1005];
int cnt, level[N], trie[N][26];
void insert(char *s, int v) {
int now = 0, len = strlen(s);
for (int i = 0; i < len; i++) {
int temp = s[i] - 'a';
if (!trie[now][temp]) trie[now][temp] = ++cnt;
now = trie[now][temp];
}
level[now] += v;
}
ll query(char *s) {
int now = 0, len = strlen(s);
for (int i = 0; i < len; i++) {
now = trie[now][s[i] - 'a'];
if (!now) return -1;
}
if (!level[now]) return -1;
else return level[now];
}
int T, n, m;
char temp[1005];
void solve() {
scanf("%d", &T);
while (T--) {
for (int i = 0; i <= cnt; i++)
memset(trie[i], 0, sizeof trie[i]), level[i] = 0;
cnt = 0;
//------------------------------------------------------初始化
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%s", mp[i] + 1);
//------------------------------------------------------ 输入
int v;
for (int i = 1; i <= m; i++) {
scanf("%s %d", temp, &v);
insert(temp, v);
}
//------------------------------------------------------建树
ll ans = 0;
int f = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int k = 0;
if (mp[i][j] == '#') continue;
while (mp[i][j] != '#' && j <= n) temp[k++] = mp[i][j++];
temp[k] = 0;
int val = query(temp);
if (val == -1) f = 1;
else ans += val;
}
}
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= n; i++) {
int k = 0;
if (mp[i][j] == '#') continue;
while (mp[i][j] != '#' && i <= n) temp[k++] = mp[i++][j];
temp[k] = 0;
int val = query(temp);
if (val == -1) f = 1;
else ans += val;
}
}
if (f) printf("-1\n");
else printf("%lld\n", ans);
}
//------------------------------------------------------查询
}
signed main() {
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
return 0;
}