The 17th Zhejiang Provincial Collegiate Programming Contest C Crossword Validation--字典树

The 17th Zhejiang Provincial Collegiate Programming Contest
题意:
给定 n ∗ n n*n nn的字符矩阵包含’#’,然后给 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值