题解:P11361 [NOIP2024] 编辑字符串

· · 题解

主要思路

算法

具体思路

代码实现

考场上写了 100 多行的代码,现在重新打过了:

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int T, n, cnt1[N][3], cnt2[N][3], a[3], b[3], ans;
char s1[N], s2[N], s3[N], s4[N];
int main()
{
    freopen("edit.in","r",stdin);
    freopen("edit.out","w",stdout);
    cin >> T;
    while(T--)
    {
        scanf("%d%s%s%s%s", &n, s1 + 1, s2 + 1, s3 + 1, s4 + 1);
        s3[0] = s4[0] = s3[n + 1] = s4[n + 1] = '0';
        // 记得清零 
        memset(cnt1, 0, sizeof cnt1);
        memset(cnt2, 0, sizeof cnt2);
        for (int i = 1; i <= n; i++) // 特判,要是左右都是零,自己自然也动不了 
        {
            if (s3[i - 1] == s3[i + 1] && s3[i - 1] == '0')
                s3[i] = '0';
            if (s4[i - 1] == s4[i + 1] && s4[i - 1] == '0')
                s4[i] = '0';
        }
        // 求每个连续 '1' 区间内的后缀和 
        for (int i = n; i > 0; i--)
        {
            if (s3[i] == '1')
                if (s3[i + 1] != '0')
                    cnt1[i][0] = cnt1[i + 1][0],
                    cnt1[i][1] = cnt1[i + 1][1],
                    cnt1[i][s1[i] - '0']++;
                else
                    cnt1[i][s1[i] - '0'] = 1;
            if (s4[i] == '1')
                if (s4[i + 1] != '0')
                    cnt2[i][0] = cnt2[i + 1][0],
                    cnt2[i][1] = cnt2[i + 1][1],
                    cnt2[i][s2[i] - '0']++;
                else
                    cnt2[i][s2[i] - '0'] = 1;
        } 
        a[0] = cnt1[1][0];
        a[1] = cnt1[1][1];
        b[1] = cnt2[1][1];
        b[0] = cnt2[1][0];
        ans = 0;
        // 使用计数器 a, b 记录后缀和 
        for (int i = 1; i <= n; i++)
        {
            if (s3[i] == '0' && s4[i] == '0') // 两个都是边界 
            {
                //直接把计数器 a, b 改成下一个点的后缀和 
                a[0] = cnt1[i + 1][0];
                a[1] = cnt1[i + 1][1];
                b[0] = cnt2[i + 1][0];
                b[1] = cnt2[i + 1][1];
                if (s1[i] == s2[i]) //相同就累计答案 
                    ans++;
            }
            else if (s3[i] == '0')
            {
                a[0] = cnt1[i + 1][0];
                a[1] = cnt1[i + 1][1];
                if (b[s1[i] - '0'] > 0)
                    b[s1[i] - '0']--, ans++;
            }
            else if (s4[i] == '0')
            {
                b[0] = cnt2[i + 1][0];
                b[1] = cnt2[i + 1][1];
                if (a[s2[i] - '0'] > 0)
                    a[s2[i] - '0']--, ans++;
            }
            else
            {
                if (a[0] > 0 && b[0] > 0)
                    ans++, a[0]--, b[0]--;
                else if (a[1] > 0 && b[1] > 0)
                    ans++, a[1]--, b[1]--;
            }
        }
        printf("%d\n", ans);
    }
    fclose(stdin);
    fclose(stdout);
    return 0; // 这是个好习惯,特别是到了比赛的时候 
}