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; }