[题解]GYM 104020D Dividing DNA
题意
给定一个 \(n\) 表示有 \(n\) 个字符串 \(q\),并且有一个字符串集合 \(S\)。(\(q\) 和 \(S\) 都是未知的)
你需要将 \(q\) 分为若干段,使得每一段都不是 \(S\) 中任意一个字符串的子串。
你可以通过询问至多 \(2n\) 次,形如 ? i j。
它将返回 present 或 absent,分别表示 \(p_ip_{i + 1}\dots p_{j - 1}\) 是 \(S\) 中某一个字符串的子串,和不是任何一个字符串的子串。
最后输出 ! x,表示将 \(q\) 最多分为 \(x\) 段,使其满足条件。
思路
用双指针 \(i,j\) 扫一遍,其中有一个贪心策略,如果 \(p_ip_{i + 1} \dots p_{j - 1}\) 已经是 \(S\) 中任意一个字符串的子串了,那么,我们就可以将 \(i \leftarrow j + 1\) 开始新一段的查询。
那么,可以保证,询问次数最多为 \(2n\)。
Code
#include <bits/stdc++.h>
#define re register
using namespace std;
int n,ans;
int main(){
cin >> n;
for (re int i = 0,j = 0;j < n;){
string op;
cout << "? " << i << " " << j + 1 << "\n";
cin >> op;
if (op[0] == 'a'){
ans++;
i = j + 1;
j++;
}
else j++;
}
cout << "! " << ans;
return 0;
}

浙公网安备 33010602011771号