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

}