The 17th Zhejiang Provincial Collegiate Programming Contest
题意:
给定
n
∗
n
n*n
n∗n的字符矩阵包含’#’,然后给
m
m
m个字符串和其权值。
有两种方式读字符矩阵:
1.从左到右读:从起始位置到末尾,遇到‘#’停止
2.从上到下读:从起始位置到末尾,遇到‘#’停止
问所读出的字符是否都在给定的
m
m
m个字符串内,没有输出-1,否则输出权值和。
读懂后很容易知道是字典树的题目,对
m
m
m个字符先建立
t
r
i
e
trie
trie然后对每个读出来的字符进行查询
注意每次
t
t
t后后清空
t
r
i
e
trie
trie,清空的方式要注意!
#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
template<class...Args>
void debug(Args... args) {//Parameter pack
auto tmp = { (cout << args << ' ', 0)... };
cout << "\n";
}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
const ll N = 4e6 + 5;
const ll MOD = 998244353;
const ll INF = 0x7ffffffff;
int trie[N][26];
int pos = 1;
ll w[N];
void insert(string s, int val) {
int p = 0;
int L = s.length();
for (int i = 0; i < L; i++) {
int n = s[i] - 'a';
if (!trie[p][n])trie[p][n] = pos++;
p = trie[p][n];
}
w[p] += val;
}
ll find(string s) {
int p = 0;
int L = s.length();
for (int i = 0; i < L; i++) {
int n = s[i] - 'a';
if (!trie[p][n])return 0;
p = trie[p][n];
}
return w[p];
}
void init() {
for (int i = 0; i <= pos; i++) {
memset(trie[i], 0, sizeof trie[i]);
w[i] = 0;
}
pos = 1;
}
string room[1005];
ll solve(int n) {
ll ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {//确定起始点
if (room[i][j] == '#')continue;
string temp;
while (j < n && room[i][j] != '#') temp+=room[i][j++];//遇到#或者到末尾
ll tt = find(temp);
ans += tt;
if (tt == 0)return -1;
}
}
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {//确定起始点
if (room[i][j] == '#')continue;
string temp;
while (i < n && room[i][j] != '#') temp+=room[i++][j];
ll tt = find(temp);
ans += tt;
if (tt == 0)return -1;
}
}
return ans;
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--) {
init();
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> room[i];
while (m--) {
string s;
int val;
cin >> s >> val;
insert(s, val);
}
cout << solve(n) << "\n";
}
return 0;
}