【2021京东秋招】01比

问题

小明有一个只包含0和1的字符串,现在小明希望将整个字符串尽可能的切割成多个字符串,要求是每个字符串里面0出现的次数和1出现的次数的比例是一致的。

解释:假设一个字符串出现0的次数是a次,出现1的次数是b另一个字符串出现0的次数是c次,出现1的次数是d次,那么这两个字符串01出现次数比例相同表示a:b=c:d,即 a*d=b*c。注意这里a,b,c,d都是可以为0的。现在对于一个字符串的所有前缀字符串,输出最多可以切割成多少个符合要求的字符串。

输入描述:
第一行一个整数n,表示01字符串的长度,1<=n<=500000第二行一个长度为n的01字符串。
输出描述:
一行n个整数,第i个数表示原字符串中下标由0到i组成的前缀字符串可以切割出多少符合要求的字符串。

示例

输入: 9
010100001
输出: 1 1 1 2 1 2 1 1 3

解答

#include <iostream>
#include <map>

using namespace std;

int _gcd(int a, int b) {
    if (b == 0) return a;
    return _gcd(b, a % b);
}

int main() {
    int n; cin >> n;
    string s; cin >> s;
    map<pair<int, int>, int> mp;
    int n0 = 0, n1 = 0;
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == '0') n0++;
        else n1++;
        if (!n0 || !n1) cout << i + 1 << ' ';
        else {
            int gcd = _gcd(n0, n1);
            int ans = ++mp[{n0 / gcd, n1 / gcd}];
            cout << ans << ' ';
        }
    }
    cout << endl;
}

重点思路

题目需要求数值呈一定比例的关系。若a:b=c:d,则a、b和c、d除以对应的最小公倍数后可以被约为相同的两个数。

使用动态规划,两数除以其最小公倍数后的两个数作为状态量,这个状态量保存可被切割的次数。遍历整个字符串,每次都将该状态量对应的结果加1。例如010101,可分为3组,当前已经得知0101为2,所以在此基础上+1输出3即可。

posted @ 2021-08-22 15:19  tmpUser  阅读(56)  评论(0编辑  收藏  举报