题意:
找到一个串调整后可以组成回文串的所有子串
思路:
由于序列可以重新调整,所以就与字符串的顺序无关,我们只需要关心个数就可以。容易发现,组成回文串,在回文串中奇数字符的个数只能是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;
}
京公网安备 11010502036488号