首页 > 代码库 > hdu 4909 String (map + 状压)
hdu 4909 String (map + 状压)
题目大意:
给定一个可能含‘?’的字符串。然后问这个字符串有多少个子串是含有所有的字符都只出现两次。
其中‘?‘ 可以被替换成任意字符,也可以被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; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。