NWERC-2018 Equality Control 语法树 大模拟
题意
现给出表达式,表达式中包含([],contract,sort,shuffle)。即序列,拼接,排序,随机。
给出两个表达式,问这两个表达式的序列的出现概率相同。
input
concat(shuffle([1,2]),shuffle([1,2]))
shuffle([1,2,1,2])
output
not equal
input
sorted(concat([3,2,1],[4,5,6]))
[1,2,3,4,5,6]
output
equal
input
concat(sorted([4,3,2,1]),shuffle([1]))
concat(concat([1,2,3],shuffle([4])),sorted([1]))
output
equal
分析
为了使问题得到简化,发现几处性质:
- shuffle中的数字如果都相同则这个shuffle没有意义
- contract可以无视
- 若出现sort和shuffle嵌套出现,外层的才发挥作用
- 判定是否等价的两个条件:所有shuffle的存在区间相等,其他数位置大小都相等
代码
此题实现有点复杂,贴的大神代码,用来学习
typedef pair<vector<int>, vector<pii> > ret;
ret get(string s) {
int n = s.length();
vector<int> a, sum(n, -1);
for (int i = 0, j ; i < n; i = j + 1) {
j = i;
if (s[i] >= '0' && s[i] <= '9') {
int x = 0;
while (j < n && s[j] >= '0' && s[j] <= '9') {
x = x * 10 + s[j] - '0';
j++;
}
sum[j - 1] = a.size();
a.push_back(x);
}
}
vector<pii> seg;
for (int i = 0, j; i < n; i = j + 1) {
j = i;
if (s[i] != 's') continue;
int cnt = 0;
while (j < n && (s[j] < '0' || s[j] > '9')) {
if (s[j] == '(') cnt++;
j++;
}
int l = INF, r = -1;
while (j < n && cnt > 0) {
if (s[j] == '(') cnt++;
if (s[j] == ')') cnt--;
if (sum[j] != -1) {
l = min(l, sum[j]);
r = max(r, sum[j]);
}
j++;
}
if (l > r) continue;
sort(a.begin() + l, a.begin() + r + 1);
if (s[i + 1] == 'h' && a[l] != a[r])
seg.push_back(make_pair(l, r));
}
return make_pair(a, seg);
}
int main() {
string s1, s2;
cin >> s1 >> s2;
ret A = get(s1);
ret B = get(s2);
if (A == B) puts("equal");
else puts("not equal");
}