ARC099F Eating Symbols Hard 题解
题意
- 有一个长度为 的整数序列 ,和一个整数 ,一开始均为 。
- 对于一个仅包含
+-><的字符串,按顺序依次执行每个字符对应的操作,可以得到新的 序列。 - 每个字符对应的操作如下:
+: 加上 。-: 减去 。>: 加上 。<: 减去 。
- 现在有一个长度为 的仅包含
+-><的字符串 ,问有多少个 的非空子串得到的 序列与 得到的 序列一样。 - 。
题解
首先对于 显然可以 hash,hash 函数设为模意义下的 ,其中 是一个自己设定的 base,注意可能要多个 base/mod。
对于一个操作序列,我们可以得到其操作完后的 hash 值以及 所在的位置 ,显然这个信息是可以合并的,。
预处理出 的每个前缀 对应的 ,题目要求 与 得到的 相等,等价于 与 得到的 相等,即 。
从左往右扫 ,用个 map 记录 的值的个数即可,时间复杂度 。
代码
const int N = 2.5e5 + 7, M = 2;
int n;
char s[N];
struct H {
vector<modint> a;
inline H() { a.resize(M); }
inline modint &operator [] (int i) { return a[i]; }
inline friend bool operator < (H x, H y) { return x.a < y.a; }
inline friend H operator + (H x, H y) {
for (int i = 0; i < M; i++) x[i] += y[i];
return x;
}
inline friend H operator - (H x, H y) {
for (int i = 0; i < M; i++) x[i] -= y[i];
return x;
}
inline friend H operator * (H x, H y) {
for (int i = 0; i < M; i++) x[i] *= y[i];
return x;
}
} a[N], x, y, h[N];
map<H, int> f;
ll ans;
int main() {
srand(time(0));
rd(n), rds(s, n);
for (int i = 0; i < M; i++)
a[0][i] = 1, x[i] = rdm(1, P - 1), y[i] = 1 / x[i];
for (int i = 1; i <= n; i++)
switch (s[i]) {
case '+' : h[i] = h[i-1] + (a[i] = a[i-1]); break;
case '-' : h[i] = h[i-1] - (a[i] = a[i-1]); break;
case '>' : h[i] = h[i-1], a[i] = a[i-1] * x; break;
case '<' : h[i] = h[i-1], a[i] = a[i-1] * y; break;
}
for (int i = 1; i <= n; i++) ++f[h[i-1]+h[n]*a[i-1]], ans += f[h[i]];
print(ans);
return 0;
}
评论
暂无已公开评论。