• C -Concatenating Teams (字符串hash)


    一个比较关键的地方是, 集合中不存在相同的字符串。

    还有就是对字符串按长度从小到大排序, 排序后就简单了很多

    对于 (A)​​ 集合来说, 对于一个当前串, 可以枚举它的前缀, 看之前是否出现过,如果出现过, 把后半部分存下来

    对于 (B) 集合来说, 对于一个当前串, 可以枚举它的后缀, 如果之前出现过, 把前半部分存下来

    并存下每个 hash 值对应的原来位置

    在统计答案的时候,

    对于集合 A , 对于一个当前串, 枚举它的前缀, 如果出现过,并且后半部分在 B 中作为差值出现过, 则说明该串和它的前缀串都不是特殊的, 利用之前存下来的 hashpos 的映射, 可以找到这个前缀的位置, 给他们俩都打上标记

    对于 B 也是类似的操作

    使用 hash + map 即可实现

    碰到一个奇怪的地方, 以下是一份 wa 掉的代码

    const ull base = 163;
    void input(){
        cin >> s;
        len = s.size();
        hash = new ull[len];
        for(int i = 0;i < len;i++){
            if(i == 0) hash[i] = s[i] - 'a';
            else hash[i] = base * hash[i-1] + s[i] - 'a';
        }
    }
    

    问题在于 s[i] - 'a' , 直接使用 s[i] 即可 AC

    是从碰撞的概率来解释吗, 没有仔细考虑过, 可以 m 一下

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef unsigned long long ull;
    const int N = 1e6 + 10, M = 1e5 + 10;
    const ull base = 163;
    
    ull p[N];
    void init(){
        p[0] = 1;
        for(int i = 1;i < N;i++) p[i] = p[i-1] * base;
    }
    struct HashString{
        string s;
        ull* hash;
        int len;
    
        void input(){
            cin >> s;
            len = s.size();
            hash = new ull[len + 10];
            for(int i = 0;i < len;i++){
                if(i == 0) hash[i] = ull(s[i]);
                else hash[i] = base * hash[i-1] + ull(s[i]);
            }
        }
        ull get(int l,int r){
            if(l == 0) return hash[r];
            return hash[r] - hash[l-1] * p[r-l+1];
        }
        ull getHash(){ return hash[len - 1]; }
    }s[M], t[M];
    
    int n, m;
    map<ull, int> visA, posA;
    map<ull, int> visB, posB;
    int a[N], b[N];
    int main() {
        //HashString::init();
        ios::sync_with_stdio(false);
        cin >> n >> m;
        init();
        for (int i = 1; i <= n; i++) s[i].input();
        for (int j = 1; j <= m; j++) t[j].input();
    
        auto cmp = [](HashString& a, HashString& b){
            return a.len < b.len;
        };
        sort(s + 1,s + 1 + n, cmp);
        sort(t + 1,t + 1 + m, cmp);
        for(int i = 1;i <= n;i++){
            posA[s[i].getHash()] = i;
            for(int j = 0;j < s[i].len - 1;j++){
                ull preHash = s[i].get(0, j);
                if(posA.count(preHash)){
                    //cout << s[i].s.substr(j + 1, s[i].len - 1 - j) << '
    ';
                    visA[s[i].get(j + 1, s[i].len - 1)] = true;
                }
            }
        }
    
        for(int i = 1;i <= m;i++){
            posB[t[i].getHash()] = i;
            for(int j = 0;j < t[i].len - 1;j++){
                ull sufHash = t[i].get(j + 1, t[i].len - 1);
                if(posB.count(sufHash)){
                    //cout << t[i].s.substr(0, j + 1) << '
    ';
                    visB[t[i].get(0, j)] = true;
                }
            }
        }
    
        for(int i = 1;i <= n;i++){
            for(int j = 0;j < s[i].len - 1;j++){
                if(posA.count(s[i].get(0, j)) and visB.count(s[i].get(j + 1, s[i].len - 1))){
                    a[i] = a[posA[s[i].get(0, j)]] = 1;
                }
            }
        }
        for(int i = 1;i <= m;i++){
            for(int j = 0;j < t[i].len - 1;j++){
                if(posB.count(t[i].get(j + 1, t[i].len - 1)) and visA.count(t[i].get(0, j))){
                    b[i] = b[posB[t[i].get(j + 1, t[i].len - 1)]] = 1;
                }
            }
        }
        int ansA = n - accumulate(a + 1,a + 1 + n, 0);
        int ansB = m - accumulate(b + 1,b + 1 + m, 0);
        cout << ansA << ' ' << ansB << '
    ';
    
    }
    
  • 相关阅读:
    springboot controller传参,对象映射
    将已有的lng lat 字段转换成point类型字段
    导入csv 到mysql数据库
    spring 数据库字段映射
    spring restTemplate使用方法
    mongo 大数据量更新注意事项
    mongo大数据量更新服务端超时解决: Cursor not found, cursor id: 82792803897
    JS 判断是否为null
    JS 日期格式化
    杨氏矩阵:查找x是否在矩阵中,第K大数
  • 原文地址:https://www.cnblogs.com/sduwh/p/15352264.html
Copyright © 2020-2023  润新知