• BZOJ 2434 阿狸的打字机


    题意 : 回答第x个模式串在第y个模式串中出现了几次。数据范围\(\sum_n,\sum_m,q\leq10^5\)

    显然可以离线,对于相同y的询问集中处理,暴跳fail的时候开个桶丢进去,最后把有用的提出来。

    但是还是太慢了。

    考虑问题本质:对于一组询问\(x,y\)实际上是在问属于串\(y\)的节点有多少\(fail\)边指向\(x\)

    可以注意到每个点有且仅有一个\(fail\) 于是从这个点的\(fail\)向这个点连边

    然后就是dfs序BIT维护

    但是插入串串太慢了

    我们考虑在原来的trie树上走,进入一个点时+1,离开时-1,避免了重复插入删除。

    这样对于不同的\(x\)也能继续进行回答。

    因为没特判没有关于落在这个点上的串的询问导致RE了一上午

    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    const int N = 1e5 + 7;
    int pcnt = 1, endp[N], ecnt, last[N];
    struct trie {int son[26], vis[26], fail, fa, end, sum;} t[N];
    struct graph {int next, to;} e[N*5];
    inline void add(int u, int v) {e[++ecnt].next = last[u], e[ecnt].to = v, last[u] = ecnt;}
    int xcnt;
    inline void ins(char *ss) {
      int lens = strlen(ss), p = 1;
      for (int i = 0; i < lens; i++) {
        if (ss[i] == 'B') p = t[p].fa;
        else if (ss[i] == 'P') endp[++xcnt] = p, t[p].sum++, t[p].end = xcnt;
        else {
          if (!t[p].son[ss[i] - 'a']) t[p].son[ss[i] - 'a'] = ++pcnt, t[pcnt].fa = p;
          p = t[p].son[ss[i] - 'a'];
        } 
      }
    }
    inline void getfail() {
      std :: queue<int> que;
      t[1].fail = 1;
      for (int i = 0; i < 26; i++) if (t[1].son[i]) 
        que.push(t[1].son[i]), t[t[1].son[i]].fail = 1;
      else t[1].son[i] = 1;
      while (!que.empty()) {
        int u = que.front(); que.pop();
        for (int i = 0; i < 26; i++) if (t[u].son[i]) 
          t[t[u].son[i]].fail = t[t[u].fail].son[i], que.push(t[u].son[i]);
        else t[u].son[i] = t[t[u].fail].son[i];
      }
    }
    int dfn[N], c[N*10], low[N];int cnt;
    inline int lbt(int x) {return (x & (-x));}
    inline void modify(int x, int k) {while(x <= cnt) c[x] += k, x += lbt(x);}
    inline int getc(int x) {int res = 0;while(x) res += c[x], x -= lbt(x);return res;} 
    inline void dfs1(int x) { 
      dfn[x] = ++cnt; 
      for (int i = last[x]; i; i = e[i].next) dfs1(e[i].to); 
      low[x] = cnt;
    } 
    struct ques {int x, y, id, ans;} q[N];
    bool operator < (ques a, ques b) {return a.y < b.y;}
    int lastans[N], sum[N];
    char ss[N]; int n, ql[N], qr[N];
    inline void dfs2(int x) {
      modify(dfn[x], 1); 
      if (t[x].end && ql[t[x].end]) 
       for (int i = ql[t[x].end]; i <= qr[t[x].end]; i++) 
        q[i].ans = getc(low[endp[q[i].x]]) - getc(dfn[endp[q[i].x]] - 1);
      for (int i = 0; i < 26; i++) if (t[x].vis[i]) dfs2(t[x].vis[i]);
      modify(dfn[x], -1);
    }
    int main() {
      scanf("%s", ss), ins(ss), scanf ("%d", &n); 
      for (int i = 1; i <= pcnt; i++)for (int j = 0; j < 26; j++) t[i].vis[j] = t[i].son[j];
      for (int i = 1; i <= n; i++) scanf ("%d%d", &q[i].x, &q[i].y), q[i].id = i;
      std :: sort (&q[1], &q[n + 1]);getfail();
      for (int i = 2; i <= pcnt; i++) add(t[i].fail, i); dfs1(1);
      for (int i = 1, opt = 1; i <= n; i = opt) {
        ql[q[i].y] = i; while(q[opt].y == q[i].y) opt++; qr[q[i].y] = opt - 1;
      } dfs2(1);
      for (int i = 1; i <= n; i++) lastans[q[i].id] = q[i].ans;
      for (int i = 1; i <= n; i++) printf("%d\n", lastans[i]);
    return 0;
    }
    
  • 相关阅读:
    Codeforces Round #350 (Div. 2) F. Restore a Number 模拟
    Codeforces Round #374 (Div. 2) C. Journey DP
    Codeforces Round #375 (Div. 2) D. Lakes in Berland DFS
    Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) D. Generating Sets 堆
    Ubuntu 安装 搜狗输入法
    Ubuntu 搜索不到WIFI或连接不上的解决方法
    Ubuntu 线缆被拔出问题
    Codeforces Round #357 (Div. 2) D. Gifts by the List DFS
    Codeforces Round #357 (Div. 2) C. Heap Operations 优先队列
    Codeforces Round #356 (Div. 2) C. Bear and Prime 100 交互题
  • 原文地址:https://www.cnblogs.com/cjc030205/p/11638070.html
Copyright © 2020-2023  润新知