您的位置:首页 > 其它

山科校赛——字符串“水”题(二进制异或+配对计数技巧)

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: