HDU 4909 String 统计+状压

因为连续异或满足区间减法性质,所以可以状压之后用异或来判断是否为符合条件的单词并且存储次数

一开始用map,一直超时。虽然直接用开1<<26的数组内存存的下,但是memset的时间肯定会超,但是只要在每次循环之后把加过的值减掉就可以绕过memset了。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;
const int maxn = 30000 + 5;
char buf[maxn];
int len,spos,val[maxn];
int mp[1 << 26];
bool vis[27];

LL solve(int l,int r) {
    if(l > r) return 0;
    LL ret = 0;
    int nowval = 0;
    mp[0]++;
    for(int i = l;i <= r;i++) if(val[i] >= 0) {
        nowval ^= (1 << val[i]);
        ret += mp[nowval];
        mp[nowval]++;
    } else ret += mp[nowval],mp[nowval]++;
    nowval = 0;
    mp[0] = 0;
    for(int i = l;i <= r;i++) if(val[i] >= 0) {
        nowval ^= (1 << val[i]);
        mp[nowval] = 0;
    }
    return ret;
}

int main() {
    int T; scanf("%d",&T);
    while(T--) {
        memset(vis,0,sizeof(vis));
        scanf("%s",buf + 1);
        len = strlen(buf + 1);
        spos = -1;
        for(int i = 1;i <= len;i++) {
            if(buf[i] == ‘?‘) spos = i;
            //转化成数字
            val[i] = buf[i] - ‘a‘;
            if(buf[i] != ‘?‘) vis[val[i]] = true;
        }
        if(spos == -1) cout << solve(1,len) << endl;
        else {
            LL ans = solve(1,len);
            LL rest = solve(1,spos - 1) + solve(spos + 1,len);
            int cnt = 0;
            for(int i = 0;i < 26;i++) if(vis[i]) {
                val[spos] = i; ans += solve(1,len);
                cnt++;
            }
            cout << ans - cnt * rest << endl;
        }
    }
    return 0;
}

  

HDU 4909 String 统计+状压

时间: 2024-08-03 04:08:47

HDU 4909 String 统计+状压的相关文章

[BestCoder Round #3] hdu 4909 String (状压,计数)

String Problem Description You hava a non-empty string which consists of lowercase English letters and may contain at most one '?'. Let's choose non-empty substring G from S (it can be G = S). A substring of a string is a continuous subsequence of th

hdu 4909 String (map + 状压)

题目大意: 给定一个可能含'?'的字符串.然后问这个字符串有多少个子串是含有所有的字符都只出现两次. 其中'?' 可以被替换成任意字符,也可以被remove... 思路分析: 这是bestcoder的round #3的第三题. 这道题的做法和 4908 的做法差不多. 我们把 '?' 左右两边的状态分别处理出来. 然后用map 计数.然后枚举左边的状态.同时枚举? 对应的字符. 然后去寻找右边对应的状态,此时 ans 就可以加上答案. 注意的是要考虑到以 ? 结尾的情况.所以在 ? 的状态要和上

hdu 2825 aC自动机+状压dp

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5640    Accepted Submission(s): 1785 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

hdu 3247 AC自动+状压dp+bfs处理

Resource Archiver Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)Total Submission(s): 2382    Accepted Submission(s): 750 Problem Description Great! Your new software is almost finished! The only thing left to

HDU 1074 Doing Homework(状压DP)

Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will r

HDU 4924 Football Manager(状压DP)

题目连接 : http://acm.hdu.edu.cn/showproblem.php?pid=4924 题意 : n(<=20)个人选出11个人作为首发组成a-b-c阵容,每个人都有自己擅长的位置,并且每个人和其他人会有单向的厌恶和喜欢关系,每个人对于自己擅长的位置都有两个值CA和PA,有喜欢或者厌恶关系的两个人在一起也会影响整个首发的CA总值,要求选出一套阵容使得CA最大,或者CA一样的情况下PA最大. 思路 : 状压搞,dp[s]s的二进制表示20个人中选了那几个人,然后规定选进来的顺序

HDU 4909 String(组合数学)

HDU 4909 String 题目链接 题意:给定一个字符串全是小写字符,可能有一个位置为?,问号可以替代任何字符,也可以删掉,问有多少连续字串满足所有字母是偶数个 思路:组合数学,计算所有前最串的各个字母的奇偶状态,用一个01串表示,然后记录下个数,对于每个相同的状态,任选两个就能得到一个子序列,答案为所有C(num, 2)的和. 但是这个问题多了一个?的情况,但是没关系,可以枚举?,然后把序列分为3部分去考虑,?之前,?之后,和包含了?的串分开考虑即可 代码: #include <cstd

hdu 4909 String(计数)

题目链接:hdu 4909 String 题目大意:给定一个字符串,由小写字母组成,最多包含一个问号,问号可以表示空或者任意一个字母.问有多少个子串,字母出现的次数均为偶数. 解题思路:因为最多又26个字母,对应每个字母的奇数情况用1表示,偶数情况用0.将一个前缀串表示成一个二进制数.然后对于每种相同的数s,任选两个即为一种可行子串(组合数学). 接着对于有问号的情况枚举一下问号替代的字符,然后对于问号后面的状态都要再加上一个该字符.这时计算个数时就要将前后分开讨论了. 这题交C++,结果卡FS

HDU 5765 Bonds(状压DP)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5765 [题目大意] 给出一张图,求每条边在所有边割集中出现的次数. [题解] 利用状压DP,计算不同的连通块,对于每条边,求出两边的联通块的划分方案数,就是对于该点的答案. [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int n,m,T,Cas=1