hdu 4909 String
字母出现次数的奇偶关系,可以用状态压缩和位异或的形式表示。由于数据范围是0~2^25,没法直接开数组,所以用到map容器需要注意的是:如果仅仅只是为了查看map<key,value>中键是否存在,最好使用map::find(key)函数,直接用map[key]的值来判断会格外增加一倍的时间
#include <cstdio> #include <map> using namespace std; const int MAXN = 20005; int T, n, res, pos, z, k, o, p; int AA[30]; char ss[MAXN]; map<int,int> mp1, mp2; map<int,int>::iterator it; void solve(map<int,int> &mp, map<int,int> &mq) { int i, j; for (it = mp.begin(); it!=mp.end();++it) { z = it->second; k = it->first; for (i = 0; i<26; ++i) { j = k^AA[i]; if (mq.find(j) != mq.end()) res += z*mq[j]; } res += z*mq[k]; } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif for (int i = 0; i< 26; ++i) AA[i] = 1<<i; scanf("%d", &T); while (T--) { scanf("%s", ss); mp1.clear(); mp2.clear(); pos = -1; for ( n = 0; ss[n]; ++n) if (ss[n] == '?') pos = n; res = pos!=-1; p = 0; for (int i = pos-1; i>= 0; --i) { o = ss[i]-'a'; p = p^AA[o]; if (!p) ++res; res += mp1[p]; mp1[p]++; } p = 0; for (int i = pos+1; i< n; ++i) { o = ss[i]-'a'; p = p^AA[o]; if (!p) ++res; res += mp2[p]; mp2[p]++; } if (pos != -1) { for (it = mp1.begin(); it!=mp1.end();++it) { z = it->second; k = it->first; if (0 == (k & (k-1))) res += z; } for (it = mp2.begin(); it!=mp2.end();++it) { z = it->second; k = it->first; if (0 == (k & (k-1))) res += z; } if (mp1.size() < mp2.size()) solve(mp1, mp2); else solve(mp2, mp1); } printf("%d\n", res); } return 0; }