• 牛客-富豪凯匹配串(bitset)


    题目传送门

    sol1:用bitset来维护,其实感觉挺暴力的,不怎么会用bitset,借着这道题学习一下。

    • bitset暴力维护
      #include "bits/stdc++.h"
      #define debug puts("what the fuck");
      using namespace std;
      const int MAXN = 1010;
      char s[MAXN];
      bitset<1010> bs[2][MAXN];
      int main() {
          int n, m, q;
          scanf("%d%d", &n, &m);
          for (int i = 1; i <= n; i++) {
              scanf("%s", s + 1);
              for (int j = 1; s[j]; j++)
                  bs[s[j] ^ '0'][j][i] = 1;
          }
          scanf("%d", &q);
          for (int i = 1; i <= q; i++) {
              scanf("%s", s + 1);
              bitset<1010> res;
              res.set();
              for (int j = 1; s[j]; j++) {
                  if (s[j] == '_') continue;
                  res &= bs[s[j] ^ '0'][j];
              }
              printf("%d
      ", res.count());
          }
          return 0;
      }

    sol2:一开始做这题,看到能有多少个匹配上的字符串联想到的是字典树,但是不断优化还是超时。然后跟一位网友学到了开两颗字典树然后匹配的方法。

    • 字典树
      #include "bits/stdc++.h"
      using namespace std;
      #define debug puts("what the fuck");
      typedef long long LL;
      typedef pair<int, int> PII;
      const int INF = 0x3f3f3f3f;
      const int MOD = 1e9 + 7;
      const int MAXNODE = 3e6 + 10;
      const int MAXN = 3010;
      int cnt[MAXNODE], ans[MAXNODE];
      int res[MAXN];
      vector<int> q[MAXNODE];
      struct Trie {
          int son[MAXNODE][3];
          int tot;
          void insert(char* s, int v, int op) {
      //        puts(s);
              int p = 0;
              for (int i = 0; s[i]; i++) {
                  int id = (s[i] == '_') ? 2 : s[i] ^ '0';
                  if (!son[p][id]) son[p][id] = ++tot;
                  p = son[p][id];
      //            printf("	%d %c", p, s[i]);
              }
      //        puts("");
              if (op == 1) cnt[p] += v;
              else q[p].push_back(v);
          }
      } t1, t2;
      char s[MAXN];
      void merge(int p1, int p2, int p, int m) {
          if (p == m) {
              ans[p2] += cnt[p1];
      //        printf("	 %d %d
      ", p1, p2);
              return;
          }
          if (t2.son[p2][0] && t1.son[p1][0]) merge(t1.son[p1][0], t2.son[p2][0], p + 1, m);
          if (t2.son[p2][1] && t1.son[p1][1]) merge(t1.son[p1][1], t2.son[p2][1], p + 1, m);
          if (t2.son[p2][2]) {
              if (t1.son[p1][0]) merge(t1.son[p1][0], t2.son[p2][2], p + 1, m);
              if (t1.son[p1][1]) merge(t1.son[p1][1], t2.son[p2][2], p + 1, m);
          }
      }
      int main() {
          int n, m, qq;
          scanf("%d%d", &n, &m);
          for (int i = 1; i <= n; i++) {
              scanf("%s", s);
              t1.insert(s, 1, 1);
          }
          scanf("%d", &qq);
          for (int i = 1; i <= qq; i++) {
              scanf("%s", s);
              t2.insert(s, i, 2);
          }
          merge(0, 0, 0, m);
          for (int i = 1; i <= t2.tot; i++) {
              for (auto index : q[i]) {
                  res[index] = ans[i];
              }
          }
          for (int i = 1; i <= qq; i++)
              printf("%d
      ", res[i]);
          return 0;
      }

      代码妙在离线后的匹配最多只要把两颗字典树都跑一边,复杂度应该是两颗字典树的节点数。网上看到另一种字典树写法分类讨论,如果询问中'_'的 个数小于20就用暴力,感觉在卡数据,不过比赛的时候这种投机的方法也未尝不可。

  • 相关阅读:
    C++的预处理(Preprocess)
    【转】深入分析Sleep(0)与Sleep(1)的区别
    【转】两个算法题,感觉挺有意思
    【转】求一个类的sizeof应考虑的问题
    const关键字总结
    C++11各编译器支持情况对比
    【转】C# 创建window服务
    关于C++中char型数组、指针及strcpy函数的细节观察
    用过的shell命令——持续更新
    初试rails 3.1
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11666320.html
Copyright © 2020-2023  润新知