贪心

题目大意

给定一个循环节 ,求给定的字符距离它右边最近的 的距离,求最大值。

思路

贪心,我们可以先思考没有循环。我们首先从前往后慢慢扫描,如果字符符合要求,我们就记录下这个字符的位置。这里我们只用记录最小值

如果我们遇到了字符 ,那么直接记录答案,并且分节,因为这里是求最近的字符

现在考虑循环。我们知道,相同的循环节如果我们直接记录,那么可能会存在跨过循环节的现象。但是我们知道,如果一个循环节里面有 ,那么不会存在两个循环节都找不到答案的情况;如果没有 ,则无解。我们只需将字符串拷贝一遍即可。

判断贪心正确性

对于每一个给定的字符,它的右边只有一个答案。而如果没有分节,最小值肯定是最优的,没有必要把所有给定字符的位置全部记录下来,因为它距离右边的第一个 肯定是最远的,因此这个贪心算法是完全正确的。

代码

#include <iostream>
#include <cstring>  // 使用string类进行操纵,可以更好地连接字符串
using namespace std;
 
int t, n, ind = 1e9, ans = -1;
// 细节*1:ind需要记录最小值,ans可能存在0的情况,保险
char c;
string s;
 
int main() {
    for (cin >> t; t; --t) {
        cin >> n >> c >> s;
        s += s  /*调用string重载运算符拷贝字符串*/ , 
        ans = -1, ind = 1e9;  // 细节*2:多组数据记得清空!
        for (int i = 0; i < s.size(); ++i) {  //遍历每个字符
            if (s[i] == c) {  // 如果是开头
                ind = min(ind, i);  // 记录最优值
            } 
            if (s[i] == 'g') {  // 细节*3:有可能给定字符就是g,不可写成else if
                ans = max(ans, i - ind);  // 记录答案
                ind = 1e9;  // 细节*4:此时已经分节了,ind需要重新计算
            }
        }
        cout << ans << '\n';
    }
    return 0;
}