牛客等级之题N1(8.13场)3的倍数

题目链接:https://ac.nowcoder.com/acm/contest/7046/A

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

1、给俺点个赞呗,可以让更多的人看到这篇文章,顺便激励下我,嘻嘻。

2、老铁们,关注我的原创微信公众号**「Grand Theft Algorithm」**,专注于写算法题解 + 计算机基础知识

分析

最容易想到的办法是通过记录每个字符串中每个字母出现的次数,然后将所有n个字符串进行各种组合,确定最多可选择的字符串数。但是这样的复杂度为2的n次方,肯定不行。

所以想到用类似于前缀和的方式,遍历所有字符串过程中,判断当前遍历到的字符串的状态与之前某位置字符串状态是否相同

对于状态而言,可以用状压来完成,实际上也就是借用二进制串的方式,将当前字符串中每个字母出现的次数记录,并将26个字母的出现次数这样一个状态转换为一个数,可能出现的最大的数是3的26次方,所以声明long long型来保存。

确定了状态后,我们只需要用unordered_map哈希表记录每个遍历到的字符串的状态,并在遍历过程中每次检查当前状态是否之前出现过,若出现过说明这两个位置之间的所有字符串合在一起,所有字母出现的次数都是3的整数倍。

特判一下状态值为0的情况,此时遍历到的字符串之前所有的字符串合到一起也满足条件。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int x[26];

ll check() {
    ll res = 0;
    for(int i = 0; i < 26; i++) {
        res = 3 * res + x[i];
    }
    return res;
}

int main() {
    int t;
    cin >> t;
    unordered_map<ll, int> mp;
    int res = 0;
    for(int j = 1; j <= t; j++) {
        string s;
        cin >> s;
        int len = s.size();
        for(int i = 0; i < len; i++) {
            x[s[i] - 'A'] = (x[s[i] - 'A'] + 1) % 3;
        }
        ll pos = check();
        //cout << "pos = " << pos << endl;
        if(pos == 0) {
            res = j;
        } else if(mp[pos] > 0) {
            res = max(res, j - mp[pos]);
        } else {
            mp[pos] = j;
        }
    }
    cout << res << endl;
}

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

1、给俺点个赞呗,可以让更多的人看到这篇文章,顺便激励下我,嘻嘻。

2、老铁们,关注我的原创微信公众号**「Grand Theft Algorithm」**,专注于写算法题解 + 计算机基础知识

猜你喜欢

转载自blog.csdn.net/weixin_42396397/article/details/107975834