题目大意:
给定一个可能含‘?’的字符串。然后问这个字符串有多少个子串是含有所有的字符都只出现两次。
其中'?' 可以被替换成任意字符,也可以被remove...
思路分析:
这是bestcoder的round #3的第三题。
这道题的做法和 4908 的做法差不多。
我们把 ‘?’ 左右两边的状态分别处理出来。
然后用map 计数。然后枚举左边的状态。同时枚举? 对应的字符。
然后去寻找右边对应的状态,此时 ans 就可以加上答案。
注意的是要考虑到以 ? 结尾的情况。所以在 ? 的状态要和上一个相同。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#define maxn 20005
using namespace std;
char str[maxn];
int st[maxn];
map<int,int>lef;
map<int,int>rig;
map<int,int>mp;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
lef.clear(),rig.clear(),mp.clear();
scanf("%s",str+1);
int pos=0;
int len=strlen(str+1);
for(int i=1;i<=len;i++)
{
if(str[i]=='?'){
pos=i,st[i]=st[i-1];
}
else {
st[i]=(st[i-1]^(1<<(str[i]-'a')));
}
}
for(int i=0;i<=len;i++){
mp[st[i]]++;
if(pos && i<pos){
lef[st[i]]++;
}
if(pos && i>=pos){
rig[st[i]]++;
}
}
int ans=0;
if(pos){
for(map<int,int>::iterator it = lef.begin();it!=lef.end();it++){
int x=it->first;
for(int j=0;j<26;j++){
int y=(x^(1<<j));
map<int,int>::iterator ct = rig.find(y);
if(ct!=rig.end())
{
ans+=(it->second)*(ct->second);
}
}
}
}
for(map<int,int>::iterator it = mp.begin();it!=mp.end();it++)
ans+=(it->second*(it->second-1))/2;
printf("%d\n",ans);
}
return 0;
}