UVALive 6284 Hyperdrome 位运算+has
2015-10-09 23:22
375 查看
题意:给一个长度为3∗105的字符串,判断有多个子串[l,r]重新排列之后可以是回文串
因为字符是′a′−′z′以及′A′−′Z′,那么我们可以用一个long long的二进制来标示某个区间该字符出现的次数,如果为奇数对应位则为1,如果为偶数则对应位为0。显然,如果该区间的字符可以重新排列组成回文串,那么该区间内1的个数<=1。
以上,以下。
假设知道区间[1,r]的“状态”,那么我们可以找是否存在l,使得[l,r]的“状态”中1的个数<=1,也就是:
已知[1,r],求
1)[1,l−1]^[l,r]==0中的l的个数
2)[1,l−1]^[l,r]结果中1的个数=1中的l的个数,l>1
然后枚举的时候hash保存一下所有的[1,l]的值出现的次数
map。。T了。。改后向星过。。。
代码:
因为字符是′a′−′z′以及′A′−′Z′,那么我们可以用一个long long的二进制来标示某个区间该字符出现的次数,如果为奇数对应位则为1,如果为偶数则对应位为0。显然,如果该区间的字符可以重新排列组成回文串,那么该区间内1的个数<=1。
以上,以下。
假设知道区间[1,r]的“状态”,那么我们可以找是否存在l,使得[l,r]的“状态”中1的个数<=1,也就是:
已知[1,r],求
1)[1,l−1]^[l,r]==0中的l的个数
2)[1,l−1]^[l,r]结果中1的个数=1中的l的个数,l>1
然后枚举的时候hash保存一下所有的[1,l]的值出现的次数
map。。T了。。改后向星过。。。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <map> using namespace std; int getnum(char ch){ if(ch>='a'&&ch<='z')return ch-'a'; else return ch-'A'+26; } typedef long long LL; const int Mod = 100009; struct Edge { LL to;int next,cnt; Edge(){} Edge(LL _to,int _next,int _cnt):to(_to),next(_next),cnt(_cnt){} }e[Mod*100]; int head[Mod+10],tot; void init(){ memset(head,-1,sizeof(head)); tot=0; } void Add(LL x){ int t=x%Mod; for(int i=head[t];~i;i=e[i].next){ if(e[i].to==x){ ++e[i].cnt; return ; } } e[tot]=Edge(x,head[t],1); head[t]=tot++; } int GetVal(LL x){ int t=x%Mod; for(int i=head[t];~i;i=e[i].next){ if(e[i].to==x)return e[i].cnt; } return 0; } //map <LL,int> mm; //map <LL,int> ::iterator it; char strs[100000*3 + 100]; int main(){ int n; while(~scanf("%d",&n)){ scanf("%s",strs); LL pre=0; init(); Add(0); //mm.clear(); //mm.insert(pair<LL,int>(0,1)); LL ans=0; for(int i=0;i<n;i++){ pre^=1LL<<getnum(strs[i]); ans+=GetVal(pre); //it=mm.find(pre); //if(it!=mm.end()){ //ans+=it->second; //} for(int i=0;i<52;i++){ ans+=GetVal(pre^(1LL<<i)); //it=mm.find(pre^(1LL<<i)); //if(it!=mm.end()){ //ans+=it->second; //} } Add(pre); //it=mm.find(pre); //if(it==mm.end())mm.insert(pair<LL,int>(pre,1)); //else ++mm[pre]; } printf("%lld\n",ans); } return 0; }
相关文章推荐
- mysql binlog二进制日志详解
- 详解C++编程中对二进制文件的读写操作
- 整理C# 二进制,十进制,十六进制 互转
- PHP has encountered an Access Violation
- c#二进制逆序方法详解
- JS幻想 读取二进制文件第1/2页
- 使用jscript实现二进制读写脚本代码
- C#二进制序列化实例分析
- PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
- javascript 二进制运算技巧解析
- 如何判断一个整数的二进制中有多少个1
- MSSQL 将截断字符串或二进制数据问题的解决方法
- 二进制中1的个数
- C++ 十进制转换为二进制的实例代码
- C语言十进制转二进制代码实例
- C++二进制翻转实例分析
- PowerShell把IP地址转换成二进制的方法
- 科学知识:二进制、八进制、十进制、十六进制转换
- C#读取二进制文件方法分析
- Shell脚本中不同进制数据转换的例子(二进制、八进制、十六进制、base64)