• luogu P4482 [BJWC2018] Border 的四种求法


    题目传送门

      传送门

    题目大意

      区间border。

      照着金策讲稿做。

    Code

      1 /**
      2  * luogu
      3  * Problem#P4482
      4  * Accepted
      5  * Time: 8264ms
      6  * Memory: 37924k
      7  */
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 
     12 template <typename T>
     13 void pfill(T* pst, const T* ped, T val) {
     14     for ( ; pst != ped; *(pst++) = val);
     15 }
     16 
     17 const int N = 2e5 + 5;
     18 const int bzmax = 19;
     19 const signed int inf = (signed) (~0u >> 2);
     20 
     21 typedef class SparseTable {
     22     public:
     23         int n;
     24         int *ar;
     25         int log2[N];
     26         int f[N][bzmax];
     27 
     28         SparseTable() {    }
     29         
     30         void init(int n, int* ar) {
     31             this->n = n;
     32             this->ar = ar;
     33             log2[1] = 0;
     34             for (int i = 2; i <= n; i++)
     35                 log2[i] = log2[i >> 1] + 1;
     36             for (int i = 0; i < n; i++)
     37                 f[i][0] = ar[i];
     38             for (int j = 1; j < bzmax; j++)
     39                 for (int i = 0; i + (1 << j) - 1 < n; i++)
     40                     f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
     41         }
     42 
     43         int query(int l, int r) {
     44             int d = log2[r - l + 1];
     45             return min(f[l][d], f[r - (1 << d) + 1][d]);
     46         }
     47 } SparseTable;
     48 
     49 typedef class Pair3 {
     50     public:
     51         int x, y, id;
     52 
     53         Pair3() {    }
     54         Pair3(int x, int y, int id):x(x), y(y), id(id) {    }
     55 } Pair3;
     56 
     57 typedef class SuffixArray {
     58     protected: 
     59         Pair3 T1[N], T2[N];
     60         int cnt[N];
     61 
     62     public:
     63         int n;
     64         char *str;
     65         int sa[N], rk[N], hei[N];
     66         SparseTable st;
     67 
     68         void set(int n, char* str) {
     69             this->n = n;
     70             this->str = str;
     71             memset(sa, 0, sizeof(sa));
     72             memset(rk, 0, sizeof(rk));
     73             memset(hei, 0, sizeof(hei));
     74         }
     75 
     76         void radix_sort(Pair3* x, Pair3* y) {
     77             int m = max(n, 256);
     78             memset(cnt, 0, sizeof(int) * m);
     79             for (int i = 0; i < n; i++)
     80                 cnt[x[i].y]++;
     81             for (int i = 1; i < m; i++)
     82                 cnt[i] += cnt[i - 1];
     83             for (int i = 0; i < n; i++)
     84                 y[--cnt[x[i].y]] = x[i];
     85 
     86             memset(cnt, 0, sizeof(int) * m);
     87             for (int i = 0; i < n; i++)
     88                 cnt[y[i].x]++;
     89             for (int i = 1; i < m; i++)
     90                 cnt[i] += cnt[i - 1];
     91             for (int i = n - 1; ~i; i--)
     92                 x[--cnt[y[i].x]] = y[i];
     93         }
     94 
     95         void build() {
     96             for (int i = 0; i < n; i++)
     97                 rk[i] = str[i];
     98             for (int k = 1; k <= n; k <<= 1) {
     99                 for (int i = 0; i + k < n; i++)
    100                     T1[i] = Pair3(rk[i], rk[i + k], i);
    101                 for (int i = n - k; i < n; i++)
    102                     T1[i] = Pair3(rk[i], 0, i);
    103                 radix_sort(T1, T2);
    104                 int diff = 1;
    105                 rk[T1[0].id] = 1;
    106                 for (int i = 1; i < n; i++)
    107                     rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff);
    108                 if (diff == n)
    109                     break;
    110             }
    111             for (int i = 0; i < n; i++)
    112                 sa[--rk[i]] = i;
    113         }
    114 
    115         void get_height() {
    116             for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) {
    117                 if (rk[i]) {
    118                     j = sa[rk[i] - 1];
    119                     while (i + k < n && j + k < n && str[i + k] == str[j + k])    k++;
    120                     hei[rk[i]] = k;
    121                 }
    122             }        
    123         }
    124 
    125         void init_st() {
    126             st.init(n, hei);
    127         }
    128 
    129         int lcp(int x1, int x2) {
    130             if (x1 == x2)
    131                 return n - x1 + 1;
    132             x1 = rk[x1], x2 = rk[x2];
    133             if (x1 > x2)
    134                 swap(x1, x2);
    135             return st.query(x1 + 1, x2);
    136         }
    137         
    138         int compare(int l1, int r1, int l2, int r2) {
    139             int len_lcp = lcp(l1, l2);
    140             int len1 = r1 - l1 + 1, len2= r2 - l2 + 1;
    141             if (len_lcp >= len1 && len_lcp >= len2)
    142                 return 0;
    143             if (len_lcp < len1 && len_lcp < len2)
    144                 return (str[l1 + len_lcp] < str[l2 + len_lcp]) ? (-1) : (1);
    145             return (len_lcp >= len1) ? (-1) : (1);
    146         }
    147 
    148         int query(int u, int v) {    // u, v -> sa
    149             if (u == v)
    150                 return n - sa[u];
    151             return st.query(u + 1, v);
    152         }
    153 
    154         const int& operator [] (int p) {
    155             return sa[p];
    156         }
    157 
    158         const int& operator () (int p) {
    159             return hei[p];
    160         }
    161 } SuffixArray;
    162 
    163 namespace IPM { // Internal Pattern Matching
    164 
    165 typedef class MatchingData {
    166     public:
    167         int a0, a1;
    168         int amount;
    169 
    170         MatchingData() : amount(0) {    }
    171         explicit MatchingData(int a0) : a0(a0), a1(a0), amount(1) {    }
    172         MatchingData(int a0, int a1) : a0(a0), a1(a1), amount(1 + (a0 != a1)) {    }
    173         MatchingData(int a0, int a1, int amount) : a0(a0), a1(a1), amount(amount) {    }
    174         MatchingData(int* a, int amount) : amount(amount) {
    175             if (amount == 0)
    176                 return;
    177             if (amount == 1)
    178                 a0 = a1 = a[0];
    179             else if (amount >= 2) {
    180                 a0 = a[0], a1 = a[1];
    181                 int d = a1 - a0;
    182                 for (int i = 2; i < amount; i++)
    183                     if (a[i] - a[i - 1] != d)
    184                         assert(false);
    185             }
    186         }
    187         
    188         boolean included(int x) {
    189             if (!amount)
    190                 return false;
    191             boolean aflag = (x == a0 || x == a1);
    192             if (amount <= 2 || aflag)
    193                 return aflag;
    194             x -= a0;
    195             int d = a1 - a0;
    196             return (!(x % d) && (x / d >= 0 && x / d < amount));
    197         }
    198 
    199         int indexOf(int x) {
    200             if (!included(x))
    201                 return -1;
    202             return (x - a0) / (a1 - a0);
    203         }
    204 
    205         int last() {
    206             return value(amount - 1);
    207         }
    208 
    209         int value(int n) {
    210             return a0 + (a1 - a0) * n;
    211         }
    212 
    213         int dif() {
    214             return a1 - a0;
    215         }
    216         
    217         MatchingData operator - () {
    218             return MatchingData(-a0, -a1, amount);
    219         }
    220 
    221         MatchingData operator + (int d) {
    222             return MatchingData(a0 + d, a1 + d, amount);
    223         }
    224         
    225         MatchingData operator - (int d) {
    226             return MatchingData(a0 - d, a1 - d, amount);
    227         }
    228 
    229         MatchingData operator ~ () {
    230             if (amount <= 1)
    231                 return *this;
    232             int _a0 = value(amount - 1);
    233             int _a1 = value(amount - 2);
    234             return MatchingData(_a0, _a1, amount);
    235         }
    236 
    237         MatchingData operator & (MatchingData b) {
    238             static int tmp[6];
    239             if (!amount || !b.amount)
    240                 return MatchingData();
    241             if (amount < 3) {
    242                 int tp = 0;
    243                 for (int i = 0, x = a0, d = a1 - a0; i < amount; i++, x += d) {
    244                     if (b.included(x)) {
    245                         tmp[tp++] = x;
    246                     }
    247                 }
    248                 return MatchingData(tmp, tp);
    249             }
    250             if (b.amount < 3) {
    251                 int tp = 0;
    252                 for (int i = 0, x = b.a0, d = b.a1 - b.a0; i < b.amount; i++, x += d) {
    253                     if (included(x)) {
    254                         tmp[tp++] = x;
    255                     }
    256                 }
    257                 return MatchingData(tmp, tp);
    258             }
    259             int d = a1 - a0;
    260             assert(d == b.a1 - b.a0);
    261             int l = indexOf(b.a0), r = l + b.amount;
    262             if (l == -1)
    263                 return MatchingData();
    264             l = max(l, 0);
    265             r = min(amount, r);
    266             if (l >= r)
    267                 return MatchingData();
    268             return MatchingData(value(l), value(l + 1), r - l);
    269         }
    270 } MatchingData;
    271 
    272 int n;
    273 char* str;
    274 //int *log2;
    275 SuffixArray sa;
    276 int f[bzmax][N];
    277 
    278 inline void init(char* str, int _n) {
    279 //    log2 = new int[(n + 1)];
    280 //    log2[0] = -1;
    281 //    for (int i = 1; i <= n; i++)
    282 //        log2[i] = log2[i >> 1] + 1;
    283     n = _n;
    284     sa.set(n, str);
    285     sa.build();
    286     sa.get_height();
    287     sa.init_st();
    288     for (int k = 0; (1 << k) <= n; k++) {
    289         int* F = f[k], len = (1 << k);
    290         for (int i = 0; i + len <= n; i++)
    291             F[i] = i;
    292         sort(F, F + (n - len) + 1, [&] (const int& x, const int& y) { 
    293             int rt = sa.compare(x, x + len - 1, y, y + len - 1);
    294             if (!rt)
    295                 return x < y;
    296             return rt == -1;
    297         });        // it can be replace by radix sort
    298     }
    299 }
    300 
    301 pair<int, int> getRange(int s, int k) {
    302     int len = 1 << k, l = 0, r = n - len, mid;
    303     int* F = f[k], L, R;
    304     while (l <= r) {
    305         mid = (l + r) >> 1;
    306         if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) == 1)
    307             l = mid + 1;
    308         else
    309             r = mid - 1;
    310     }
    311     L = r + 1;
    312     l = 0, r = n - len;
    313     while (l <= r) {
    314         mid = (l + r) >> 1;
    315         if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) >= 0)
    316             l = mid + 1;
    317         else
    318             r = mid - 1;
    319     }
    320     R = l - 1;
    321     return pair<int, int>(L, R);    
    322 }
    323 
    324 int succ(int s, int k, int i, int L, int R) {    // pos >= i
    325     int len = 1 << k, l = 0, r = n - len;
    326     int mid;
    327     int *F = f[k];
    328     if (L > R)
    329         return inf;
    330     l = L, r = R;
    331     while (l <= r) {
    332         mid = (l + r) >> 1;
    333         if (F[mid] >= i)
    334             r = mid - 1;
    335         else
    336             l = mid + 1;
    337     }
    338     if (r == R)
    339         return inf;
    340     return F[r + 1];
    341 }
    342 
    343 int pred(int s, int k, int i) { //<= i
    344     int len = 1 << k, l = 0, r = n - len;
    345     int L, R, mid;
    346     int *F = f[k];
    347     while (l <= r) {
    348         mid = (l + r) >> 1;
    349         if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) == 1)
    350             l = mid + 1;
    351         else
    352             r = mid - 1;
    353     }
    354     L = r + 1;
    355     l = 0, r = n - len;
    356     while (l <= r) {
    357         mid = (l + r) >> 1;
    358         if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) >= 0)
    359             l = mid + 1;
    360         else
    361             r = mid - 1;
    362     }
    363     R = l - 1;
    364     if (L > R)
    365         return -1;
    366     l = L, r = R;
    367     while (l <= r) {
    368         mid = (l + r) >> 1;
    369         if (F[mid] <= i)
    370             l = mid + 1;
    371         else
    372             r = mid - 1;
    373     }
    374     if (l == L)
    375         return -1;
    376     return F[l - 1];
    377 }
    378 
    379 // rt - lt + 1 = 2 ^ k
    380 MatchingData query(int ls, int rs, int lt, int k) {
    381     int len = 1 << k;
    382     pair<int, int> range = getRange(lt, k);
    383     int a0 = succ(lt, k, ls, range.first, range.second);
    384     if (a0 + len - 1 > rs)
    385         return MatchingData();
    386     int a1 = succ(lt, k, a0 + 1, range.first, range.second);
    387     if (a1 + len - 1 > rs)
    388         return MatchingData(a0);
    389     int an = pred(lt, k, rs - len + 1);
    390     assert(an >= ls);
    391     MatchingData rt (a0, a1);
    392     rt.amount = N;
    393     rt.amount = rt.indexOf(an) + 1;
    394     return rt;
    395 }
    396 
    397 }
    398 
    399 using IPM :: MatchingData;
    400 
    401 int n, m;
    402 char str[N];
    403 
    404 inline void init() {
    405     scanf("%s", str);
    406     n = strlen(str);
    407     IPM :: init(str, n);
    408 }
    409 
    410 int query(int l, int r) {
    411     int t = 0, half_len = (r - l + 2) >> 1;
    412     while ((1 << t) < half_len)
    413         t++;
    414     for (int i = t; ~i; i--) {
    415         int len = min(r - l, 1 << (i + 1)), hlen = (1 << i);
    416         MatchingData md_l = IPM :: query(l, l + len - 1, r - hlen + 1, i);
    417         MatchingData md_r = IPM :: query(r - len + 1, r, l, i);
    418         md_l = md_l - l + hlen;
    419         md_r = -(~md_r) + (r + 1);
    420         md_l = md_l & md_r;
    421         if (md_l.amount)
    422             return md_l.last();
    423     }
    424     return (str[l] == str[r] && l < r);
    425 }
    426 
    427 inline void solve() {
    428     scanf("%d", &m);
    429     int l, r;
    430     while (m--) {
    431         scanf("%d%d", &l, &r);
    432         printf("%d
    ", query(--l, --r));
    433     }
    434 }
    435 
    436 int main() {
    437 //    freopen("border.in", "r", stdin);
    438 //    freopen("border.out", "w", stdout);
    439     init();
    440     solve();
    441     return 0;
    442 }
  • 相关阅读:
    01、python数据分析与机器学习实战——python数据分析处理库Pandas
    01、python数据分析与机器学习实战——python数据分析处理库Pandas
    01、python数据分析与机器学习实战——python数据分析处理库Pandas
    从显示一张图片开始学习OpenGL ES
    从显示一张图片开始学习OpenGL ES
    C#中【pdb】文件
    C#中【pdb】文件
    SQLServer 中的存储过程中判断临时表是否存在,存在则删除临时表
    SQLServer 中的存储过程中判断临时表是否存在,存在则删除临时表
    C# 网络编程之webBrowser乱码问题及解决知识
  • 原文地址:https://www.cnblogs.com/yyf0309/p/10232477.html
Copyright © 2020-2023  润新知