【CF1660C】Get an Even String(字符串,贪心)

【题目描述】
一个字符串 a = a 1 a 2 … a n a=a_1a_2\dots a_n a=a1a2an称为偶数字符串当且仅当满足条件:该字符串是由长度为 2 2 2的连续且相同的字符组成的子串组成的,即同时满足以下两个条件:

  • 字符串的长度为偶数;
  • 对于每个奇数位置 i ( 1 ≤ i ≤ n − 1 ) i(1\le i\le n-1) i(1in1),都满足 a i = a i + 1 a_i=a_{i+1} ai=ai+1

例如,字符串ttaabboooottrrrroouuuuuuuukk是偶数的,字符串aaaabababba则不是。
现在给定一个只由小写字母组成的字符串 s s s,请你求出最少删去多少个字符可以使得 s s s变成偶数字符串。

【输入格式】
第一行一个整数 t ( 1 ≤ t ≤ 1 0 4 ) t(1\le t\le 10^4) t(1t104),表示测试样例的数量。
对于每组测试样例,输入一个字符串 s ( 1 ≤ ∣ s ∣ ≤ 2 × 1 0 5 ) s(1\le |s|\le 2\times 10^5) s(1s2×105) ∣ s ∣ |s| s表示字符串 s s s的长度。
数据保证所有测试数据中 ∣ s ∣ |s| s的总和不超过 2 × 1 0 5 2\times 10^5 2×105

【输出格式】
对于每组测试样例输出一个整数,表示最少需要删去多少个字符才能使 s s s变成偶数字符串。

【输入样例】

6
aabbdabdccc
zyx
aaababbb
aabbcc
oaoaaaoo
bmefbmuyw

【输出样例】

3
3
2
0
2
7

【分析】


从前往后遍历整个字符串,使用数组 s t [ i ] st[i] st[i]表示之前是否出现过字符 i i i(将 a ∼ z a\sim z az映射成 0 ∼ 25 0\sim 25 025),如果已经出现过,那么加上当前出现的这个字符就组成了两个相同字符的字符串,因此将其加入到答案字符串中,我们只需要记录长度,因此答案字符串的长度 m + 2 m+2 m+2,然后将其间的其他字符都删去,也就是将 s t st st数组清空,继续往后寻找。这样能保证当 s t [ i ] = = t r u e st[i]==true st[i]==true的时候,在 i i i之前的字符都还没有凑出一对,因此这一对在这整个区间中是最先被凑出来的,根据贪心的思想就将这一对计入答案中,其余的字符都删去即可。最后的结果即为 n − m n-m nm


【代码】

#include 
#include 
#include 
using namespace std;

const int N = 200010;
char s[N];
bool st[26];

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        cin >> s;
        int n = strlen(s), m = 0;
        memset(st, false, sizeof st);
        for (int i = 0; i < n; i++)
            if (st[s[i] - 'a']) m += 2, memset(st, false, sizeof st);
            else st[s[i] - 'a'] = true;
        cout << n - m << endl;
    }
    return 0;
}

你可能感兴趣的:(CodeForces,贪心算法,算法,c++)