• BZOJ3881 Divljak


    解:对被包含的那些串建AC自动机。

    每次加一个串,就在AC自动机上面跑,可知能够跑到一些节点。

    这些节点都是一些前缀的形式,我们跳fail树就是跳后缀,这样就能够得到所有能匹配的子串。

    我们分别对AC自动机中的每个串计算答案。

    就是要求一些节点到根路径的并集,并对其权值 + 1。查询就查对应节点。

    然后有个trick就是lca处 - 1,节点处 + 1,然后求子树和。、

      1 #include <bits/stdc++.h>
      2 
      3 const int N = 100010, M = 2000010;
      4 
      5 struct Edge {
      6     int nex, v;
      7 }edge[M]; int tp;
      8 
      9 int tr[M][26], fail[M], tot = 1, n, ed[N];
     10 std::queue<int> Q;
     11 char str[N];
     12 int e[M], pos[M], siz[M], num, ST[M << 1][22], d[M], stk[M], pw[M << 1], top, pos2[M << 1], num2;
     13 
     14 inline void add(int x, int y) {
     15     tp++;
     16     edge[tp].v = y;
     17     edge[tp].nex = e[x];
     18     e[x] = tp;
     19     return;
     20 }
     21 
     22 void DFS(int x) {
     23     pos[x] = ++num;
     24     pos2[x] = ++num2;
     25     ST[num2][0] = x;
     26     siz[x] = 1;
     27     for(int i = e[x]; i; i = edge[i].nex) {
     28         int y = edge[i].v;
     29         d[y] = d[x] + 1;
     30         DFS(y);
     31         ST[++num2][0] = x;
     32         siz[x] += siz[y];
     33     }
     34     return;
     35 }
     36 
     37 inline void prework() {
     38     for(int i = 2; i <= num2; i++) {
     39         pw[i] = pw[i >> 1] + 1;
     40     }
     41     for(int j = 1; j <= pw[num2]; j++) {
     42         for(int i = 1; i + (1 << j) - 1 <= num2; i++) {
     43             if(d[ST[i][j - 1]] < d[ST[i + (1 << (j - 1))][j - 1]])
     44                 ST[i][j] = ST[i][j - 1];
     45             else
     46                 ST[i][j] = ST[i + (1 << (j - 1))][j - 1];
     47         }
     48     }
     49     /*for(int j = 0; j <= pw[num2]; j++) {
     50         printf("j = %d : ", j);
     51         for(int i = 1; i + (1 << j) - 1 <= num2; i++) {
     52             printf("%d ", ST[i][j]);
     53         }
     54         puts("");
     55     }*/
     56     return;
     57 }
     58 
     59 inline bool cmp(const int &a, const int &b) {
     60     return pos[a] < pos[b];
     61 }
     62 
     63 inline int lca(int x, int y) {
     64     //printf("lca : %d %d = ", x, y);
     65     x = pos2[x]; y = pos2[y];
     66     if(x > y) std::swap(x, y);
     67     int t = pw[y - x + 1];
     68     if(d[ST[x][t]] < d[ST[y - (1 << t) + 1][t]])
     69         return ST[x][t];
     70         //{ printf("%d 
    ", ST[x][t]); return ST[x][t]; }
     71     else
     72         return ST[y - (1 << t) + 1][t];
     73         //{ printf("%d 
    ", ST[y - (1 << t) + 1][t]); return ST[y - (1 << t) + 1][t]; }
     74 }
     75 
     76 namespace ta {
     77     int ta[M];
     78     inline void add(int x, int v) {
     79         for(int i = x; i <= tot; i += i & (-i)) {
     80             ta[i] += v;
     81         }
     82         return;
     83     }
     84     inline int getSum(int x) {
     85         int ans = 0;
     86         for(int i = x; i >= 1; i -= i & (-i)) {
     87             ans += ta[i];
     88         }
     89         return ans;
     90     }
     91     inline int ask(int l, int r) {
     92         return getSum(r) - getSum(l - 1);
     93     }
     94 }
     95 
     96 inline void insert(int id) {
     97     int n = strlen(str), p = 1;
     98     for(int i = 0; i < n; i++) {
     99         int f = str[i] - 'a';
    100         if(!tr[p][f]) {
    101             tr[p][f] = ++tot;
    102         }
    103         p = tr[p][f];
    104     }
    105     ed[id] = p;
    106     return;
    107 }
    108 
    109 inline void BFS() {
    110     Q.push(1);
    111     fail[1] = 1;
    112     while(!Q.empty()) {
    113         int x = Q.front();
    114         Q.pop();
    115         for(int f = 0; f < 26; f++) {
    116             if(!tr[x][f]) continue;
    117             int y = tr[x][f], j = fail[x];
    118             while(j != 1 && !tr[j][f]) {
    119                 j = fail[j];
    120             }
    121             if(x != 1 && tr[j][f]) {
    122                 j = tr[j][f];
    123             }
    124             fail[y] = j;
    125             Q.push(y);
    126         }
    127     }
    128     return;
    129 }
    130 
    131 inline void add() {
    132     int n = strlen(str), p = 1;
    133     top = 0;
    134     for(int i = 0; i < n; i++) {
    135         int f = (str[i]) - 'a';
    136         while(p != 1 && !tr[p][f]) p = fail[p];
    137         if(tr[p][f]) p = tr[p][f];
    138         if(p > 1) stk[++top] = p;
    139     }
    140     if(!top) return;
    141     std::sort(stk + 1, stk + top + 1, cmp);
    142     top = std::unique(stk + 1, stk + top + 1) - stk - 1;
    143     for(int i = 1; i <= top; i++) {
    144         ta::add(pos[stk[i]], 1);
    145         if(i < top) {
    146             int z = lca(stk[i], stk[i + 1]);
    147             ta::add(pos[z], -1);
    148         }
    149     }
    150     return;
    151 }
    152 
    153 inline int ask(int x) {
    154     return ta::ask(pos[x], pos[x] + siz[x] - 1);
    155 }
    156 
    157 int main() {
    158     int m;
    159     scanf("%d", &n);
    160     for(int i = 1; i <= n; i++) {
    161         scanf("%s", str);
    162         insert(i);
    163     }
    164     BFS();
    165     ///
    166     for(int i = 2; i <= tot; i++) {
    167         add(fail[i], i);
    168         //printf("add %d %d 
    ", fail[i], i);
    169     }
    170     d[1] = 1;
    171     DFS(1);
    172     prework();
    173 
    174     scanf("%d", &m);
    175     for(int i = 1, f, x; i <= m; i++) {
    176         scanf("%d", &f);
    177         if(f == 1) {
    178             scanf("%s", str);
    179             add();
    180         }
    181         else {
    182             scanf("%d", &x);
    183             printf("%d
    ", ask(ed[x]));
    184         }
    185     }
    186     return 0;
    187 }
    MLE代码
  • 相关阅读:
    IIS6为应用程序池**提供服务的进程与 World Wide Web Publishing 服务通信时遇到致命错误
    C# WINFORM 强制让窗体获得焦点
    数据库性能优化详解
    sqlserver 2008 修改表结构不能保存
    SQL性能优化
    aspnet打印 设置(页脚 一些数据显示在打印页的最下面)
    图片转成byte数组
    在配置文件中定义初始值然后读取
    DOM编程
    html动态显示时间
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10495697.html
Copyright © 2020-2023  润新知