山科校赛——字符串“水”题(二进制异或+配对计数技巧)
2017-05-01 15:48
176 查看
问题 A: 字符串“水”题
时间限制: 1 Sec 内存限制: 128 MB提交: 214 解决: 40
[提交][状态][讨论版]
题目描述
给出一个长度为 n 的字符串(1<=n<=100000),求有多少个连续字串中所有的字母都出现了偶数次。
输入
第一行一个正整数 T,表示数据组数(1 <= T <= 10)。 接下来 T 行,每行有一个只包含小写字母的字符串。
输出
每个答案输出满足要求字符串个数。每个答案input
3
a
aabbcc
abcabc
output
0
6
1
(引用了别的同学的题解)
题意:给出一个长度为n的字符串(1<=n<=100000),求有多少个连续字串中所有的字母都出现了偶数次。
分析:
1、从左到右扫一遍字符串,利用状态压缩记录下截止到当前位置各字母是奇数还是偶数,若奇数,则为1,否则为0。
2、试想,如果扫一个字符串时,截止到某种状态所有个数为奇数的字母与截止到之前某种状态所有个数为奇数的字母完全相同,则这两个状态之间的子串所有的字母一定都是出现了偶数次。(奇-奇=偶)
而,因为奇数用1表示,且所有个数为奇数的字母相同,(eg:00010000000100000001000001与00010000000100000001000001),那么这两个状态压缩之后一定相同。
3、如果扫到的状态之前出现过,则ans+=该状态之前出现过的状态数。
eg:ababab,
扫到第一个字母a时,状态为1(00000000000000000000000001),当扫到第5个字母a时,状态又为1,则两状态之间的字母一定都是出现了偶数次。
4、对于状态为0的情况,即截止到当前状态,所有字母都出现了偶数次,则其与最初始(尚未开始扫字符串)的状态相同,可与最初始的状态构成符合要求的连续子串,所以status[0]=1。
eg:abababab,
扫到第四个字母,状态为0,ans+=status[0],然后ans=1。截止到第四个字母的子串与截止到第0个字母的子串形成的连续子串,即abab,所有的字母都出现了偶数次。++status[0](状态为0的状态数又多了一个,应加1)。
扫到第八个字母,状态为0,ans+=status[0],然后ans=3。截止到第八个字母的子串分别与 截止到第0个字母的子串和截止到第四个字母的子串 形成的连续子串,即abab,所有的字母都出现了偶数次。
5、PS:status开数组的话大约6000多万,清空会超时,因此改用map。
上边题解写的太好了,我是写不出来。。(这题让我想到了KB的状压DP和山东省赛的平方数)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <stack>
using namespace std;
typedef long long ll;
#define PI 3.1415926535897932
#define E 2.718281828459045
#define INF 0xffffffff//0x3f3f3f3f
#define mod 1000000007
const int MOD=1e9+7;
const int M=1005;
int n,m;
map <int,int> has;
char str[1000005];
int main()
{
int i,j,k,t;
int tmp,wait;
scanf("%d",&t);
while(t--){
scanf("%s",str);
//memset(has,0,sizeof(has));
has.clear();
int len=strlen(str);
ll ans=0;wait=0;
has[0]=1; //我发现了一个问题,这个初值为0,就是两两的配对数,等于一,就可以推前n个的配对数
for(i=0;i<len;i++)
{
tmp=str[i]-'a';
wait^=(1<<tmp);
ans+=has[wait];
has[wait]++;
}
printf("%lld\n",ans);
}
return 0;
}
相关文章推荐
- 山科校赛 Problem A: 字符串“水”题(状态压缩)
- Visual Basic Base64编码源码:可实现对字符串(中文)和二进制文件编码
- PHP 小技巧之(3)将一个php源程序存入一个字符串变量以后,如何将其中的尾部空格,换行符以及tab,去掉呢?
- 编写的一个10进制转二进制字符串的函数
- 字符串常用技巧
- asp实现二进制字符串转换为Unicode字符串
- 把二进制的字段以字符串形式Select出来
- 把文件以二进制格式或base64字符串形式保存到数据库中,并实现下载功能源码
- 存储过程小技巧(1)----分解字符串
- 将截断字符串或二进制数据,语句终止的解决方法
- SAS命令应用高级技巧--如何从一批SCL,SOURCE文件中查找或替换某字符串
- 十进制数转二进制字符串
- 文本字符串与二进制字符串互转
- SqlException: 将截断字符串或二进制数据
- 支持中文的把普通字符串转成二进制字符串
- SAS应用技巧-快速在CATALOG的SCL中查找某字符串的方法
- ERROR JDBCExceptionReporter:46 - [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]将截断字符串或二进制数据。
- 16进制字符串转为二进制字符串
- 关于GridView的两个技巧(格式字符串和隐藏列)
- 问题集锦07:使用T-SQL导入数据时报错“将截断字符串或二进制数据”