码迷,mamicode.com
首页 > 其他好文 > 详细

[CF19C] Deletion of Repeats - 贪心,hash

时间:2021-02-18 13:14:40      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:bit   lan   ace   ring   它的   对象   就是   中间   位置   

[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]] << " ";
}

[CF19C] Deletion of Repeats - 贪心,hash

标签:bit   lan   ace   ring   它的   对象   就是   中间   位置   

原文地址:https://www.cnblogs.com/mollnn/p/14406046.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!