题目大意:
给定一个可能含‘?’的字符串。然后问这个字符串有多少个子串是含有所有的字符都只出现两次。
其中‘?‘ 可以被替换成任意字符,也可以被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; }
hdu 4909 String (map + 状压),布布扣,bubuko.com
原文地址:http://blog.csdn.net/u010709592/article/details/38364669