多校联合集训 A. 字符串“水”题 (状压+哈希)

网友投稿 644 2022-10-03

多校联合集训 A. 字符串“水”题 (状压+哈希)

多校联合集训 A. 字符串“水”题 (状压+哈希)

题目描述

给出一个长度为 n 的字符串(1<=n<=100000),求有多少个连续字串中所有的字母都出现了偶数次。

输入

第一行一个正整数 T,表示数据组数(1 <= T <= 10)。 接下来 T 行,每行有一个只包含小写字母的字符串。

输出

每个答案输出满足要求字符串个数。每个答案占一行。

样例输入

3aaabbccabcabc

样例输出

061

思路

某位学长写的题解,感觉挺详细的,所以转过来了。

从左到右扫一遍字符串,利用状态压缩记录下截止到当前位置各字母是奇数还是偶数,若奇数,则为 ​​1​​​ ,否则为 ​​0​​ 。试想,如果扫一个字符串时,截止到某种状态所有个数为奇数的字母与截止到之前某种状态所有个数为奇数的字母完全相同,则这两个状态之间的子串所有的字母一定都是出现了偶数次。(奇-奇=偶)因为奇数用1表示,且所有个数为奇数的字母相同,(eg: ​​00010000000100000001000001​​​ 与 ​​00010000000100000001000001​​ ),那么这两个状态压缩之后一定相同。如果扫到的状态之前出现过,则 ​​ans+=该状态之前出现过的状态数​​ 。eg: ​​ababab​​​ ,扫到第一个字母 ​​a​​​ 时,状态为 ​​1​​​ ( ​​00000000000000000000000001​​​ ),当扫到第 ​​5​​​ 个字母 ​​a​​​ 时,状态又为 ​​1​​ ,则两状态之间的字母一定都是出现了偶数次。对于状态为 ​​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​​ ,所有的字母都出现了偶数次。PS: ​​status​​​ 开数组的话大约 ​​6000​​​ 多万,清空会超时,因此改用 ​​map​​ 。

PS: 比赛开始的时候这道题直接用 ​​map​​ 是可以过的,不过后来数据加强了,应该也没有重判,所以原来的代码提交都会超时。

解决的办法是利用哈希来缩短每次查找的时间,之前学长们的做法都是打算用哈希链来处理的,不过我想到了用 ​​map​​ 数组处理。(突然想到了一个很好用并且很好写的解决哈希冲突的方法,感觉好开心~)

AC 代码

#include #include #include #include #include #include #include #include #include #include #include #include #define maxn 100007using namespace std;typedef long long LL;char str[110000];mapsk[maxn];void solve(){ memset(sk,0,sizeof(sk)); for(int i=0; i>T; while(T--) { cin>>str; solve(); } return 0;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:HDU 6052 To my boyfriend (计数)
下一篇:小程序管理员怎么绑定呢(小程序怎么解绑管理员)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~