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