B Hyperdrome
Kingdom Reunion
https://ac.nowcoder.com/acm/contest/7852/A
题意:
找到一个串调整后可以组成回文串的所有子串
思路:
由于序列可以重新调整,所以就与字符串的顺序无关,我们只需要关心个数就可以。容易发现,组成回文串,在回文串中奇数字符的个数只能是1个或者0个。比如 aa(0个) aba(1个) b是奇数个,a是偶数个。可以用位运算来记录当前位置以前所有数字的奇偶情况,当新添加一个字符的时候只需要将他与前一个^。
该如何判断添加一个新的字符能产生多少个新的序列呢,只需要寻找之前这个序列出现的个数,由于之前的情况与现在一样,就说明在他们之间的内容是0。但由于可以是奇数个,所以在寻找的时候,还应该找到去除一个字母的情况
代码:
代码块 #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <unordered_map> #include <bitset> using namespace std; #define ll long long #ifdef ONLINE_JUDGE #else #define scanf scanf_s #endif // ONLINE_JUDGE #define FOR(i,a,b) for(int i = a;i <= b;i++) #define ROF(i,a,b) for(int i = a;i >= b;i--) unordered_map<ll, int> mp; ll read() { ll X = 0, w = 1; char c = getchar(); while (c < '0' || c>'9') { if (c == '-') w = -1; c = getchar(); } while (c >= '0' && c <= '9') X = X * 10 + c - '0', c = getchar(); return X * w; } ll poww(ll a, ll b, ll mod) { ll base = 1; while (b) { if (b & 1) { base = base * a % mod; } b >>= 1; a = a * a % mod; } return base; } int ctoi(char c) { if (islower(c)) { return c + 1 - 'a'; } return c + 1 + 26 - 'A'; } int main() { int t; t = read(); string s; mp[0] = 1; cin >> s; ll sum = 0, ans = 0; for (int i = 0; i < s.size(); i++) { sum ^= ((ll)1 << ctoi(s[i]));//加入了这个值 FOR(j, 1, 52) { if(mp.count(sum ^ ((ll)1 << j))) ans += mp[sum ^ ((ll)1 << j)];//可以有一个是单数 } if(mp.count(sum)) ans += mp[sum]; ++mp[sum]; } cout << ans << endl; }