题目链接: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」**,专注于写算法题解 + 计算机基础知识