zoukankan      html  css  js  c++  java
  • LOJ#6041 事情的相似度

    题意:求字符串[l, r]这些前缀的两两之间最长的最长公共后缀。

    把fail树建出来,就是编号在一段区间的最深lca。

    套用我之前口胡的莫队做法可以做到O(n√n),光荣70分。

    而且我还非常SB的把原串,fail树,链表上的节点搞混了......

    这个链表是那些关键节点按照DFS序串起来的。莫队的时候注意严格按照顺序来搞...

      1 /**
      2  * There is no end though there is a start in space. ---Infinity.
      3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
      4  * Only the person who was wisdom can read the most foolish one from the history.
      5  * The fish that lives in the sea doesn't know the world in the land.
      6  * It also ruins and goes if they have wisdom.
      7  * It is funnier that man exceeds the speed of light than fish start living in the land.
      8  * It can be said that this is an final ultimatum from the god to the people who can fight.
      9  *
     10  * Steins;Gate
     11  */
     12 
     13 #include <bits/stdc++.h>
     14 
     15 const int N = 200010;
     16 
     17 struct Edge {
     18     int nex, v;
     19 }edge[N << 1]; int tp;
     20 
     21 int tot = 1, last = 1, tr[N][2], fail[N], len[N], e[N];
     22 int d[N], ST[N << 2][20], pw[N << 2], num2, pos2[N], lc[N], rc[N];
     23 int n, m, id[N], T, fr[N], pre[N], nex[N], Ans[N], id2[N], num;
     24 char str[N];
     25 
     26 struct Ask {
     27     int l, r, id;
     28     inline bool operator < (const Ask &w) const {
     29         if(fr[l] != fr[w.l]) return l < w.l;
     30         return r > w.r;
     31     }
     32 }ask[N];
     33 
     34 namespace BlockV {
     35     int cnt[N], a[N];
     36     inline void clear() {
     37         memset(cnt + 1, 0, fr[n] * sizeof(int));
     38         memset(a, 0, sizeof(a));
     39         return;
     40     }
     41     inline void insert(int x, int v) {
     42         a[x] += v;
     43         cnt[fr[x]] += v;
     44         //printf("Block add %d %d 
    ", x, v);
     45         return;
     46     }
     47     inline int getMax() {
     48         for(int i = fr[n]; i >= 0; i--) {
     49             if(cnt[i]) {
     50                 for(int j = rc[i]; j >= lc[i]; j--) {
     51                     if(a[j]) return j;
     52                 }
     53                 return -1;
     54             }
     55         }
     56         return -1;
     57     }
     58 }
     59 
     60 inline bool cmp(const int &a, const int &b) {
     61     return pos2[a] < pos2[b];
     62 }
     63 
     64 inline void add(int x, int y) {
     65     tp++;
     66     edge[tp].v = y;
     67     edge[tp].nex = e[x];
     68     e[x] = tp;
     69     return;
     70 }
     71 
     72 inline void insert(char c) {
     73     int f = c == '1', p = last, np = ++tot;
     74     last = np;
     75     len[np] = len[p] + 1;
     76     while(p && !tr[p][f]) {
     77         tr[p][f] = np;
     78         p = fail[p];
     79     }
     80     if(!p) {
     81         fail[np] = 1;
     82     }
     83     else {
     84         int Q = tr[p][f];
     85         if(len[Q] == len[p] + 1) {
     86             fail[np] = Q;
     87         }
     88         else {
     89             int nQ = ++tot;
     90             len[nQ] = len[p] + 1;
     91             fail[nQ] = fail[Q];
     92             fail[Q] = fail[np] = nQ;
     93             memcpy(tr[nQ], tr[Q], sizeof(tr[Q]));
     94             while(tr[p][f] == Q) {
     95                 tr[p][f] = nQ;
     96                 p = fail[p];
     97             }
     98         }
     99     }
    100     return;
    101 }
    102 
    103 void DFS_1(int x, int f) {
    104     pos2[x] = ++num2;
    105     ST[num2][0] = x;
    106     d[x] = d[f] + 1;
    107     for(int i = e[x]; i; i = edge[i].nex) {
    108         int y = edge[i].v;
    109         if(y == f) {
    110             continue;
    111         }
    112         DFS_1(y, x);
    113         ST[++num2][0] = x;
    114     }
    115     return;
    116 }
    117 
    118 inline void prework() {
    119     for(int i = 2; i <= num2; i++) pw[i] = pw[i >> 1] + 1;
    120     for(int j = 1; j <= pw[num2]; j++) {
    121         for(int i = 1; i <= num2; i++) {
    122             if(d[ST[i][j - 1]] < d[ST[i + (1 << (j - 1))][j - 1]])
    123                 ST[i][j] = ST[i][j - 1];
    124             else
    125                 ST[i][j] = ST[i + (1 << (j - 1))][j - 1];
    126         }
    127     }
    128     return;
    129 }
    130 
    131 inline int lca(int x, int y) {
    132     x = pos2[x], y = pos2[y];
    133     if(x > y) std::swap(x, y);
    134     int t = pw[y - x + 1];
    135     if(d[ST[x][t]] < d[ST[y - (1 << t) + 1][t]]) {
    136         return ST[x][t];
    137     }
    138     else {
    139         return ST[y - (1 << t) + 1][t];
    140     }
    141 }
    142 
    143 inline void Add(int x) {
    144     //printf("add x = %d id = %d 
    ", x, id[x]);
    145     x = id[x];
    146     if(nex[x]) pre[nex[x]] = x;
    147     if(pre[x]) nex[pre[x]] = x;
    148     if(nex[x] && pre[x]) BlockV::insert(len[lca(nex[x], pre[x])], -1);
    149     if(nex[x]) {
    150         BlockV::insert(len[lca(x, nex[x])], 1);
    151     }
    152     if(pre[x]) {
    153         BlockV::insert(len[lca(x, pre[x])], 1);
    154     }
    155     return;
    156 }
    157 
    158 inline void Del(int x) {
    159     //printf("del x = %d id = %d 
    ", x, id[x]);
    160     x = id[x];
    161     if(pre[x]) nex[pre[x]] = nex[x];
    162     if(nex[x]) pre[nex[x]] = pre[x];
    163     if(nex[x] && pre[x]) {
    164         BlockV::insert(len[lca(nex[x], pre[x])], 1);
    165     }
    166     if(nex[x]) {
    167         BlockV::insert(len[lca(x, nex[x])], -1);
    168     }
    169     if(pre[x]) {
    170         BlockV::insert(len[lca(x, pre[x])], -1);
    171     }
    172     return;
    173 }
    174 
    175 int main() {
    176     scanf("%d%d", &n, &m);
    177     T = n / sqrt(m);
    178     //printf("T = %d sqrt(m)= %d 
    ", T, (int)sqrt(m));
    179     for(int i = 1; i <= n; i++) {
    180         fr[i] = (i - 1) / T + 1;
    181         //printf("fr %d = %d 
    ", i, fr[i]);
    182     }
    183     for(int i = 1; i <= fr[n]; i++) {
    184         lc[i] = rc[i - 1] + 1;
    185         rc[i] = lc[i] + T - 1;
    186         if(i == fr[n]) rc[i] = n;
    187     }
    188     scanf("%s", str + 1);
    189     for(int i = 1; i <= m; i++) {
    190         scanf("%d%d", &ask[i].l, &ask[i].r);
    191         ask[i].id = i;
    192     }
    193     std::sort(ask + 1, ask + m + 1);
    194     for(int i = 1; i <= n; i++) {
    195         insert(str[i]);
    196         id[i] = id2[i] = last;
    197     }
    198     for(int i = 2; i <= tot; i++) {
    199         add(fail[i], i);
    200         //printf("add : %d %d 
    ", fail[i], i);
    201     }
    202     DFS_1(1, 0);
    203     prework();
    204     /// solve
    205 
    206     std::sort(id2 + 1, id2 + n + 1, cmp);
    207 
    208     int p = 1;
    209     for(int i = 1; i <= n; i++) {
    210         p = tr[p][str[i] == '1'];
    211         if(id[i] != p) {
    212             printf("ERROR! 
    ");
    213         }
    214     }
    215 
    216     for(int i = 1; i < n; i++) {
    217         int x = id2[i], y = id2[i + 1];
    218         //printf("i = %d x = %d y = %d 
    ", i, x, y);
    219         nex[x] = y;
    220         pre[y] = x;
    221         BlockV::insert(len[lca(x, y)], 1);
    222     }
    223     p = 1;
    224     int l = 1, r = n;
    225     for(int i = 1; i <= fr[n]; i++) {
    226         while(r < n) Add(++r);
    227         while(l < lc[i]) Del(l++);
    228         while(fr[ask[p].l] == i) {
    229             while(ask[p].r < r) Del(r--);
    230             while(l < ask[p].l) Del(l++);
    231             Ans[ask[p].id] = BlockV::getMax();
    232             //printf("id = %d 
    ", ask[p].id);
    233             while(lc[i] < l) Add(--l);
    234             p++;
    235         }
    236     }
    237     for(int i = 1; i <= m; i++) {
    238         printf("%d
    ", Ans[i]);
    239     }
    240     return 0;
    241 }
    70分TLE代码

    然后是启发式合并 + 树状数组 + 扫描线代码。

      1 /**
      2  * There is no end though there is a start in space. ---Infinity.
      3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
      4  * Only the person who was wisdom can read the most foolish one from the history.
      5  * The fish that lives in the sea doesn't know the world in the land.
      6  * It also ruins and goes if they have wisdom.
      7  * It is funnier that man exceeds the speed of light than fish start living in the land.
      8  * It can be said that this is an final ultimatum from the god to the people who can fight.
      9  *
     10  * Steins;Gate
     11  */
     12 
     13 #include <bits/stdc++.h>
     14 
     15 const int N = 200010;
     16 
     17 struct Edge {
     18     int nex, v;
     19 }edge[N << 1]; int tp;
     20 
     21 struct Ask {
     22     int l, r, id;
     23     Ask(int L = 0, int R = 0, int ID = 0) {
     24         l = L;
     25         r = R;
     26         id = ID;
     27     }
     28     inline bool operator < (const Ask &w) const {
     29         return l < w.l;
     30     }
     31 }ask[N], node[N * 20]; int Cnt;
     32 typedef Ask Node;
     33 
     34 char str[N];
     35 int e[N], n, m, tot = 1, last = 1, tr[N][2], fail[N], len[N], id[N], Ans[N], ta[N];
     36 std::set<int> st[N];
     37 std::set<int>::iterator it, it2;
     38 
     39 inline void add(int x, int y) {
     40     tp++;
     41     edge[tp].v = y;
     42     edge[tp].nex = e[x];
     43     e[x] = tp;
     44     return;
     45 }
     46 
     47 inline void Add(int x, int y) {
     48     //printf("add %d %d 
    ", x, y);
     49     for(int i = x; i <= n; i += i & (-i)) {
     50         ta[i] = std::max(ta[i], y);
     51     }
     52     return;
     53 }
     54 
     55 inline int Ask(int x) {
     56     //printf("ask %d 
    ", x);
     57     int ans = 0;
     58     for(int i = x; i >= 1; i -= i & (-i)) {
     59         ans = std::max(ans, ta[i]);
     60     }
     61     return ans;
     62 }
     63 
     64 inline void insert(char c) {
     65     int f = c == '1', p = last, np = ++tot;
     66     last = np;
     67     len[np] = len[p] + 1;
     68     while(p && !tr[p][f]) {
     69         tr[p][f] = np;
     70         p = fail[p];
     71     }
     72     if(!p) {
     73         fail[np] = 1;
     74     }
     75     else {
     76         int Q = tr[p][f];
     77         if(len[Q] == len[p] + 1) {
     78             fail[np] = Q;
     79         }
     80         else {
     81             int nQ = ++tot;
     82             len[nQ] = len[p] + 1;
     83             fail[nQ] = fail[Q];
     84             fail[Q] = fail[np] = nQ;
     85             memcpy(tr[nQ], tr[Q], sizeof(tr[Q]));
     86             while(tr[p][f] == Q) {
     87                 tr[p][f] = nQ;
     88                 p = fail[p];
     89             }
     90         }
     91     }
     92     return;
     93 }
     94 
     95 void DFS_1(int x) {
     96     if(id[x]) {
     97         st[x].insert(id[x]);
     98         //printf("id  %d =  %d 
    ", x, id[x]);
     99     }
    100     for(int i = e[x]; i; i = edge[i].nex) {
    101         int y = edge[i].v;
    102         DFS_1(y);
    103         /// merge
    104         if(st[x].size() < st[y].size()) {
    105             std::swap(st[x], st[y]);
    106         }
    107         for(it = st[y].begin(); it != st[y].end(); it++) {
    108             int a = *it;
    109             it2 = st[x].lower_bound(a);
    110             if(it2 != st[x].end()) {
    111                 int b = *it2;
    112                 /// node a b
    113                 if(a > b) std::swap(a, b);
    114                 node[++Cnt] = Node(a, b, len[x]);
    115                 //printf("Node : %d %d %d 
    ", a, b, len[x]);
    116             }
    117             if(it2 != st[x].begin()) {
    118                 it2--;
    119                 int b = *it2;
    120                 /// node a b
    121                 if(a > b) std::swap(a, b);
    122                 node[++Cnt] = Node(a, b, len[x]);
    123                 //printf("Node : %d %d %d 
    ", a, b, len[x]);
    124             }
    125         }
    126         for(it = st[y].begin(); it != st[y].end(); it++) {
    127             st[x].insert(*it);
    128         }
    129         st[y].clear();
    130     }
    131     return;
    132 }
    133 
    134 int main() {
    135     scanf("%d%d", &n, &m);
    136     scanf("%s", str + 1);
    137     for(int i = 1; i <= m; i++) {
    138         scanf("%d%d", &ask[i].l, &ask[i].r);
    139         ask[i].id = i;
    140     }
    141     for(int i = 1; i <= n; i++) {
    142         insert(str[i]);
    143         id[last] = i;
    144     }
    145     for(int i = 2; i <= tot; i++) {
    146         add(fail[i], i);
    147     }
    148     DFS_1(1);
    149 
    150     std::sort(ask + 1, ask + m + 1);
    151     std::sort(node + 1, node + Cnt + 1);
    152 
    153     int p1 = Cnt, p2 = m;
    154     for(int i = n; i >= 1; i--) {
    155         //printf("i = %d 
    ", i);
    156         while(node[p1].l == i) {
    157             Add(node[p1].r, node[p1].id);
    158             p1--;
    159         }
    160         while(ask[p2].l == i) {
    161             Ans[ask[p2].id] = Ask(ask[p2].r);
    162             p2--;
    163         }
    164     }
    165     for(int i = 1; i <= m; i++) {
    166         printf("%d 
    ", Ans[i]);
    167     }
    168     return 0;
    169 }
    AC代码
  • 相关阅读:
    隔壁小孩都要知道的Drupal配置
    Cobaltstrike、armitage联动
    YxCMS 1.4.7 最新版漏洞分析
    业务逻辑漏洞探索之暴力破解
    刺透内网的HTTP代理
    pwn入门之栈溢出练习
    史上最完整的MySQL注入
    ISG 2018 Web Writeup
    3-4 计算长方形的周长和面积
    【Lucene4.8教程之二】索引
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10643136.html
Copyright © 2011-2022 走看看