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 the string. if G contains '?' then '?' can be deleted or replaced by one of lowercase english letters. After that if each letter occurs even number of times in G then G is a good substring. Find number of all good substrings.
 
Input
The input consists of an integer T, followed by T lines, each containing a non-empty string. The length of the string doesn't exceed 20000.

[Technical Specification]
1 <= T <= 100
 
Output
For each test case, print a single integer which is the number of good substrings of a given string.
 
Sample Input
3 abc?ca aabbcc aaaaa
 
Sample Output
7 6 6
 
题解:用二进制模拟前缀的奇偶状态,如果一个状态x经过添加了几个字母后回到状态x,那么这几个字母肯定符合good substrings。
感受:又get到了一个新技能。同时深深佩服想出这种方法的大佬。代码有参考网上的博客,不过花了1800多秒,手动实现的map只需要300多秒。
 1 #pragma warning(disable:4996)
 2 #include<map>
 3 #include<string>
 4 #include<cstdio>
 5 #include<bitset>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 using namespace std;
10 typedef long long ll;
11 
12 const int maxn = 2e4 + 4;
13 
14 int T;
15 char s[maxn];
16 
17 int main()
18 {
19     scanf("%d", &T); while (T--) {
20         map<int, int> p;
21         scanf("%s", s);
22         int pos = -1, n = strlen(s);
23         for (int i = 0; i < n; i++) if (s[i] == '?') { pos = i; break; }
24 
25         int ans = 0, x;
26         if (pos == -1) {
27             x = 0; p[0]++;
28             for (int i = 0; i < n; i++) {
29                 x ^= 1 << (s[i] - 'a');
30                 ans += p[x];
31                 p[x]++;
32             }
33             printf("%d\n", ans);
34         }
35         else {
36             x = 0; p[0]++;
37             for (int i = 0; i <= pos - 1; i++) {
38                 x ^= 1 << (s[i] - 'a');
39                 ans += p[x];
40                 p[x]++;
41             }
42             p.clear();
43 
44             x = 0; p[0]++;
45             for (int i = pos + 1; i < n; i++) {
46                 x ^= 1 << (s[i] - 'a');
47                 ans += p[x];
48                 p[x]++;
49             }
50 
51             x = 0;
52             if (p.count(x)) ans += p[x];
53             
54             for (int i = 0; i < 26; i++) if (p.count(x ^ (1 << i))) ans += p[x ^ (1 << i)];
55 
56             for (int i = pos - 1; i >= 0; i--) {
57                 x ^= 1 << (s[i] - 'a');
58                 if (p.count(x)) ans += p[x];
59                 for (int j = 0; j < 26; j++) if (p.count(x ^ (1 << j))) ans += p[x ^ (1 << j)];
60             }
61             printf("%d\n", ans);
62         }
63     }
64     return 0;
65 }

网上大佬手动实现的map,值得学习!!!!!!!!!!!!!

 1 #pragma warning(disable:4996)
 2 #include<map>
 3 #include<string>
 4 #include<cstdio>
 5 #include<bitset>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 using namespace std;
10 typedef long long ll;
11 
12 const int maxn = 2e4 + 4;
13 
14 char s[maxn];
15 
16 struct m_map {
17     int tot, k[maxn], va[maxn];
18     int head[maxn], next[maxn];
19     m_map() { tot = 0; }
20     void clear() {
21         tot = 0;
22         memset(head, -1, sizeof(head));
23     }
24     int &get(int v) {
25         int u = v % maxn;
26         for (int i = head[u]; i != -1; i = next[i]) if (k[i] == v) return va[i];
27         k[tot] = v; va[tot] = 0;
28         next[tot] = head[u];
29         head[u] = tot;
30         return va[tot++];
31     }
32     int get2(int v) {
33         int u = v % maxn;
34         for (int i = head[u]; i != -1; i = next[i]) if (k[i] == v) return va[i];
35         return 0;
36     }
37 }mp;
38 
39 int Find(int p, int n) {
40     mp.clear();
41     mp.get(0)++;  //初始状态为0,想想"aa"这样的序列
42     int ans = 0, x = 0;
43     for (int i = p; i < n; i++) {
44         x ^= 1 << (s[i] - 'a');
45         ans += mp.get2(x);
46         mp.get(x)++;
47     }
48     return ans;
49 }
50 
51 int Find2(int p, int n) {
52     mp.clear();
53     mp.get(0)++;                //同理
54     int x = 0, ans = 0;
55     for (int i = 0; i < p; i++) {
56         x ^= 1 << (s[i] - 'a');
57         mp.get(x)++;
58     }
59     ans += mp.get2(x);
60     for (int i = 0; i < 26; i++) ans += mp.get2(x ^ (1 << i));
61     for (int i = p + 1; i < n; i++) {
62         x ^= 1 << (s[i] - 'a');
63         ans += mp.get2(x);
64         for (int j = 0; j < 26; j++) ans += mp.get2(x ^ (1 << j));
65     }
66     return ans;
67 }
68 
69 int main()
70 {
71     int T;
72     scanf("%d", &T);
73     while (T--) {
74         scanf("%s", s);
75         int p = -1, n = strlen(s);
76         for (int i = 0; i < n; i++) if (s[i] == '?') p = i;
77         if (p == -1) printf("%d\n", Find(0, n));
78         else printf("%d\n", Find(0, p) + Find(p + 1, n) + Find2(p, n));
79     }
80     return 0;
81 }

 

posted @ 2018-03-21 19:29  天之道,利而不害  阅读(193)  评论(0编辑  收藏  举报