1393 0和1相等串 鸽笼原理 || 化简dp公式

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1393

正解一眼看出来的应该是鸽笼原理。记录每个位置的前缀和,就是dp[i][1]表示前i个数中,1的个数。dp[i][0]同理。

然后计算出每一个位置的dp[i][1] - dp[i][0],如果和前面的出现相同,那么这一段就是贡献。

也可以从化简dp公式来看。

也是一样的都dp[i][0] && dp[i][1]

那么设区间为be, en

如果要相同,则需要dp[en][1] - dp[be - 1][1] == dp[en][0] - dp[be - 1][0]

化简下,就是上面的式子。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1000000 + 20;
int dp[maxn][2];
char str[maxn];
vector<int>pos[maxn * 2];
void work() {
    scanf("%s", str + 1);
    int lenstr = strlen(str + 1);
    int one = 0, zero = 0;
    for (int i = 1; i <= lenstr; ++i) {
        if (str[i] == '0') {
            zero++;
            dp[i][0] = dp[i - 1][0] + 1;
            dp[i][1] = dp[i - 1][1];
        } else {
            one++;
            dp[i][1] = dp[i - 1][1] + 1;
            dp[i][0] = dp[i - 1][0];
        }
    }
    for (int i = 0; i <= lenstr; ++i) {
        pos[dp[i][1] - dp[i][0] + lenstr].push_back(i);
    }
    int ans = 0;
    for (int i = 0; i <= 2 * lenstr; ++i) {
        if (pos[i].size() <= 1) continue;
        ans = max(ans, pos[i].back() - pos[i][0]);
    }
    cout << ans << endl;
    return;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6295096.html