AT4163 [ARC099D] Eating Symbols Hard
手玩数据,不难发现,这几种操作类似于子串哈希的过程。
区间操作序列判断相同更坚定了我们的想法,哈希解决问题。
考虑维护前缀哈希,一个区间 [ l , r ] [l,r] [l,r] 的哈希值,应该是 [ 1 , r ] [1,r] [1,r] 的哈希值,减去 [ 1 , l − 1 ] [1,l-1] [1,l−1] 移位后的哈希值,移位顺便维护一下即可。
最后双或三哈希判断,开桶记录个数即可,时间复杂度 O ( n ) \mathcal O(n) O(n)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ha putchar(' ')
#define he putchar('\n')
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(ll x)
{
if(x < 0)
{
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
const int _ = 250010 * 2;
const ll bs1 = 819, Bs1 = 783725420, md1 = 998244353, bs2 = 1989, Bs2 = 227249785, md2 = 999999607, bs3 = 1998, Bs3 = 582062931, md3 = 999967099;
ll n, As, pos[_];
ull r1, r2, r3, p1[_], P1[_], p2[_], P2[_], p3[_], P3[_], hs1[_], hs2[_], hs3[_];
char s[_];
map<tuple<int, int, int>, int> mp;
signed main()
{
n = read();
scanf("%s", s + 1);
p1[0] = P1[0] = p2[0] = P2[0] = p3[0] = P3[0] = 1;
for(int i = 1; i <= n * 2; ++i)
{
p1[i] = p1[i - 1] * bs1 % md1;
P1[i] = P1[i - 1] * Bs1 % md1;
p2[i] = p2[i - 1] * bs2 % md2;
P2[i] = P2[i - 1] * Bs2 % md2;
p3[i] = p3[i - 1] * bs3 % md3;
P3[i] = P3[i - 1] * Bs3 % md3;
}
pos[0] = n;
for(int i = 1; i <= n; ++i)
{
pos[i] = pos[i - 1];
if(s[i] == '>') pos[i] = pos[i - 1] + 1;
if(s[i] == '<') pos[i] = pos[i - 1] - 1;
if(s[i] == '+')
{
r1 = (r1 + p1[pos[i]]) % md1;
r2 = (r2 + p2[pos[i]]) % md2;
r3 = (r3 + p3[pos[i]]) % md3;
}
if(s[i] == '-')
{
r1 = (r1 + md1 - p1[pos[i]]) % md1;
r2 = (r2 + md2 - p2[pos[i]]) % md2;
r3 = (r3 + md3 - p3[pos[i]]) % md3;
}
hs1[i] = r1, hs2[i] = r2, hs3[i] = r3;
}
for(int i = n - 1; i >= 0; --i)
{
mp[{hs1[i + 1], hs2[i + 1], hs3[i + 1]}]++;
ull k1 = (hs1[i] + (r1 * ((pos[i] <= n) ? P1[n - pos[i]] : p1[pos[i] - n]) % md1)) % md1;
ull k2 = (hs2[i] + (r2 * ((pos[i] <= n) ? P2[n - pos[i]] : p2[pos[i] - n]) % md2)) % md2;
ull k3 = (hs3[i] + (r3 * ((pos[i] <= n) ? P3[n - pos[i]] : p3[pos[i] - n]) % md3)) % md3;
// cout << k1 << " " << k2 << "\n";
As += mp[{k1, k2, k3}];
}
write(As);
return 0;
}