• 牛客-富豪凯匹配串(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就用暴力,感觉在卡数据,不过比赛的时候这种投机的方法也未尝不可。

  • 相关阅读:
    个人技术博客
    第十七周19年春学习总结
    第十六周第四次实验设计报告
    第十五周第三次实验设计报告
    第十四周第二次试验设计报告
    第十三周
    第十二周
    第十一周
    第十周作业
    只为粗暴看一下ES6的字符串模板的性能
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11666320.html
Copyright © 2020-2023  润新知