zoukankan      html  css  js  c++  java
  • [CF19C] Deletion of Repeats

    [CF19C] Deletion of Repeats - 贪心,hash

    Description

    有一个字符串。它里面有许多不同的字母,这些字母用数字来标记,而且每个字母最多出现10次。现在要求按一定的规则删除字符串中的重复部分:首先找到最短的重复部分(如果有多个就选择最左边的),然后删掉它的左半部分和左边的全部字母。求最终结果。

    Solution

    删除的方式决定了我们其实只要在需要删除的时候标记一下,再次找的时候,如果枚举的对象与删除的部分有交集,就跳过

    这样相当于整个判断过程只要做一轮,换句话就是找出所有可能的最短重复部分,因为显然这种删除方式不会创造新的重复部分

    如果两个字符串相同,那么他们开头字母一定相同

    我们来枚举这个开头字母,因为出现个数不超过 10,所以我们可以暴力枚举这两个开头的位置,设为 i,j,那么中间夹住的这个串的长度就是 j-i=len,我们判断从 i,j 开头的长度为 len 的串是否相等即可

    判断的时候要按照区间长度升序进行

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    struct string_hash
    {
        vector<int> str;
        int n;
        vector<unsigned long long> p, h;
        const int bas = 1337;
        string_hash(int n, vector<int> s) : n(n), str(s)
        {
            p.resize(n + 2);
            h.resize(n + 2);
            p[0] = 1;
            for (int i = 1; i <= n; i++)
                p[i] = p[i - 1] * bas;
            for (int i = 1; i <= n; i++)
                h[i] = (h[i - 1] * bas + str[i]);
        }
        int &operator[](int id)
        {
            return str[id];
        }
        unsigned long long substrhash(int l, int r)
        {
            return (h[r] - h[l] * p[r - l]);
        }
    };
    
    signed main()
    {
        int n;
        cin >> n;
        vector<int> a(n + 2);
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        map<int, int> mp;
        vector<int> c(n + 2);
        for (int i = 1; i <= n; i++)
            mp[a[i]]++;
        int ind = 0;
        for (auto &[x, y] : mp)
            y = ++ind, c[ind] = x;
        for (int i = 1; i <= n; i++)
            a[i] = mp[a[i]];
        vector<vector<int>> pos(ind + 2);
        for (int i = 1; i <= n; i++)
            pos[a[i]].push_back(i);
        string_hash s(n, a);
        int del = 0;
        struct Range
        {
            int l, r;
            bool operator<(const Range &rhs) const
            {
                if (r - l == rhs.r - rhs.l)
                    return l < rhs.l;
                return r - l < rhs.r - rhs.l;
            }
        };
        vector<Range> range;
        for (int c = 1; c <= ind; c++)
        {
            int m = pos[c].size();
            for (int ii = 0; ii < m; ii++)
            {
                for (int jj = ii + 1; jj < m; jj++)
                {
                    int i = pos[c][ii], j = pos[c][jj];
                    range.push_back({i, j});
                }
            }
        }
        sort(range.begin(), range.end());
        for (auto [i, j] : range)
        {
            int len = j - i;
            int l1 = i, r1 = i + len - 1;
            int l2 = j, r2 = j + len - 1;
            if (r1 > n || r2 > n)
                continue;
            if (l1 <= del)
                continue;
            if (s.substrhash(l1, r1) == s.substrhash(l2, r2))
            {
                del = max(del, r1);
            }
        }
        cout << n - del << endl;
        for (int i = del + 1; i <= n; i++)
            cout << c[a[i]] << " ";
    }
    
    
  • 相关阅读:
    C#中使用Oracle存储过程返回结果集
    微信公众平台开发教程(九)微信公众平台通用开发框架
    微信公众平台开发教程(八)Session处理
    微信公众平台开发教程(七)安全策略
    微信公众平台开发教程(六)获取个性二维码
    微信公众平台开发教程(五)自定义菜单(含实例源码)
    微信公众平台开发教程(三) 基础框架搭建
    微信公众平台开发教程(一) 微信公众账号注册流程
    当"唐僧"没那么容易
    C#编程总结(六)异步编程
  • 原文地址:https://www.cnblogs.com/mollnn/p/14406046.html
Copyright © 2011-2022 走看看