字符串Hash + 树上DFS

题目来源:

2018年长沙理工大学ACM省赛选拔赛 2018年8月7日

题意:

dr所在国度的有个奇怪的规定:他们的字母不是a~z,而是用1~1000表示。
利用这个奇怪的规定,dr想出了一个好玩的游戏:首先给出n个字符串(当然每个字符用1~1000表示),然后给出有m个节点的树,节点编号1~m,这棵树以1号节点为根,每个节点都包含一个字符。现在要求用从根节点到其他m-1个节点的链上的字符组成m-1个新字符串(字符的排列顺序为从根到终点的顺序)。
是否这m-1个新字符串中的任意一个串,都与给出的n个字符串中至少一个串匹配呢?
字符串S与字符串T匹配:S是T的子串

输入:

第一行输入n和m,表示有n个字符串,树的节点数为m( n103 n ≤ 10 3 , m2105 m ≤ 2 ∗ 10 5 )
接下来n行,每行首先输入一个整数k,代表字符串长度,然后输入k个整数,代表字符串( ki=1Si2105 ∑ i = 1 k S i ≤ 2 ∗ 10 5 )
接下来一行,输入m个整数Ci​,表示树上第i个节点上的字符
接下来m−1行,每行输入2个整数u,v( 1u 1 ≤ u , vm v ≤ m ),表示u和v有一条边

输出:

输出占一行,都能匹配输出YES,否则输出NO

题解:

字符串hash的入门题,我们用unorded_map记录hash值,树上套个简单的dfs就可以遍历整个树。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <unordered_map>
#define INF 0x3f3f3f3f
#define SEED 131
using namespace std;

const int maxn = 200010;
unordered_map<unsigned long long, bool> hash_map;
unsigned long long hash_str, hash_tree[maxn];
int n, m, str_n, w[maxn], cnt, head[maxn];
struct Edge {
    int to, next;
} edge[maxn];

void init() {
    cnt = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int from, int to) {
    edge[cnt].to = to;
    edge[cnt].next = head[from];
    head[from] = cnt++;
}
bool dfs(int u, int father) {
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        if (v == father)
            continue;
        hash_tree[v] = hash_tree[u] * SEED + w[v];
        if (hash_map[hash_tree[v]] == false)
            return false;
        if (dfs(v, u) == false)//题意要求m-1中的任一个个串,所以只要有一个不满足就要返回false
            return false;
    }
    return true;
}

int main(void) {
    ios::sync_with_stdio(false);
    init();
    cin >> n >> m;
    int temp, t1, t2;
    for (int i = 1; i <= n; i++) {
        cin >> str_n;
        hash_str = 0;
        for (int j = 1; j <= str_n; j++) {
            cin >> temp;
            hash_str = hash_str * SEED + temp;
            hash_map[hash_str] = true;
        }
    }

    for (int i = 1; i <= m; i++)
        cin >> w[i];
    for (int i = 1; i <= m - 1; i++) 
        cin >> t1 >> t2,addedge(t1, t2);

    if (hash_map[w[1]] == false)
        cout << "NO" << endl;
    else {
        hash_tree[1] = w[1];
        if (dfs(1, 0))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值