zoukankan      html  css  js  c++  java
  • poj 3415 Common Substrings

    题目传送门

      传送点I

      传送点II

    题目大意

      给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量。

      根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid分组。

      分完组考虑如何统计每一组的贡献。

      对于每一组内每一对$(A_i , B_j)$考虑拆成两部分:

    • $rank(A_i) < rank(B_j)$
    • $rank(A_i) > rank(B_j)$

      然后就可以从小到大枚举每一个串,然后考虑前面的$A_i$或$B_j$的贡献。

      显然这个贡献从当前串的前一个串往前走单调不增,然后就拿个单调栈维护就完了。

    Code

      1 /**
      2  * poj
      3  * Problem#3415
      4  * Accepted
      5  * Time: 1110ms
      6  * Memory: 10232k
      7  */
      8 #include <iostream>
      9 #include <cstring>
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #ifndef WIN32
     13 #define Auto "%lld"
     14 #else
     15 #define Auto "%I64d"
     16 #endif
     17 using namespace std;
     18 typedef bool boolean;
     19 #define ll long long
     20 
     21 #define pii pair<int, int>
     22 #define fi first
     23 #define sc second
     24 
     25 const int N = 2e5 + 5;
     26 
     27 typedef class Pair3 {
     28     public:
     29         int x, y, id;
     30 
     31         Pair3() {    }
     32         Pair3(int x, int y, int id):x(x), y(y), id(id) {    }
     33 }Pair3;
     34 
     35 typedef class SuffixArray {
     36     protected: 
     37         Pair3 T1[N], T2[N];
     38         int cnt[N];
     39 
     40     public:
     41         int n;
     42         char *str;
     43         int sa[N], rk[N], hei[N];
     44 
     45         void set(int n, char* str) {
     46             this->n = n;
     47             this->str = str;
     48             memset(sa, 0, sizeof(sa));
     49             memset(rk, 0, sizeof(rk));
     50             memset(hei, 0, sizeof(hei));
     51         }
     52 
     53         void radix_sort(Pair3* x, Pair3* y) {
     54             int m = max(n, 256);
     55             memset(cnt, 0, sizeof(int) * m);
     56             for (int i = 0; i < n; i++)
     57                 cnt[x[i].y]++;
     58             for (int i = 1; i < m; i++)
     59                 cnt[i] += cnt[i - 1];
     60             for (int i = 0; i < n; i++)
     61                 y[--cnt[x[i].y]] = x[i];
     62 
     63             memset(cnt, 0, sizeof(int) * m);
     64             for (int i = 0; i < n; i++)
     65                 cnt[y[i].x]++;
     66             for (int i = 1; i < m; i++)
     67                 cnt[i] += cnt[i - 1];
     68             for (int i = n - 1; ~i; i--)
     69                 x[--cnt[y[i].x]] = y[i];
     70         }
     71 
     72         void build() {
     73             for (int i = 0; i < n; i++)
     74                 rk[i] = str[i];
     75             for (int k = 1; k < n; k <<= 1) {
     76                 for (int i = 0; i + k < n; i++)
     77                     T1[i] = Pair3(rk[i], rk[i + k], i);
     78                 for (int i = n - k; i < n; i++)
     79                     T1[i] = Pair3(rk[i], 0, i);
     80                 radix_sort(T1, T2);
     81                 int diff = 0;
     82                 rk[T1[0].id] = 0;
     83                 for (int i = 1; i < n; i++)
     84                     rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff);
     85                 if (diff == n - 1)
     86                     break;
     87             }
     88             for (int i = 0; i < n; i++)
     89                 sa[rk[i]] = i;
     90         }
     91 
     92         void get_height() {
     93             for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) {
     94                 if (rk[i]) {
     95                     j = sa[rk[i] - 1];
     96                     while (i + k < n && j + k < n && str[i + k] == str[j + k])    k++;
     97                     hei[rk[i]] = k;
     98                 }
     99             }        
    100         }
    101 
    102         const int& operator [] (int p) {
    103             return sa[p];
    104         }
    105 
    106         const int& operator () (int p) {
    107             return hei[p];
    108         }
    109 }SuffixArray;
    110 
    111 int K;
    112 int n, m;
    113 char S[N];
    114 SuffixArray sa;
    115 
    116 inline boolean init() {
    117     scanf("%d", &K);
    118     if (!(K--))
    119         return false;
    120     scanf("%s", S);
    121     n = strlen(S);
    122     S[n] = '#';
    123     scanf("%s", S + n + 1);
    124     m = strlen(S + n + 1);
    125     n += m + 1;
    126     sa.set(n, S);
    127     return true;
    128 }
    129 
    130 ll res = 0, sum;
    131 int tp = 0;
    132 pii st[N];
    133 inline void solve(int L, int R) {    // Calculate the s_i (i in [L, R))
    134     if (R - L < 2)
    135         return ;
    136     tp = sum = 0;
    137     for (int i = L, sg; i < R - 1; i++) {
    138         sg = (sa[i] < n - m - 1); 
    139         if (!sg)
    140             res += sum;
    141         while (tp && st[tp].fi >= sa(i + 1))
    142             sg += st[tp].sc, sum -= st[tp].sc * 1ll * (st[tp].fi - K), tp--;
    143         sum += (sa(i + 1) - K) * 1ll * sg;
    144         st[++tp] = pii(sa(i + 1), sg);
    145     }
    146     if (!(sa[R - 1] < n - m - 1))
    147         res += sum;
    148 
    149     tp = sum = 0;
    150     for (int i = L, sg; i < R - 1; i++) {
    151         sg = !(sa[i] < n - m - 1);
    152         if (!sg)
    153             res += sum; 
    154         while (tp && st[tp].fi >= sa(i + 1))
    155             sg += st[tp].sc, sum -= st[tp].sc * 1ll * (st[tp].fi - K), tp--;
    156         sum += (sa(i + 1) - K) * 1ll * sg;
    157         st[++tp] = pii(sa(i + 1), sg);
    158     }
    159     if (sa[R - 1] < n - m - 1)
    160         res += sum;
    161 }
    162 
    163 inline void solve() {
    164     res = 0;
    165     sa.build();
    166     sa.get_height();
    167     
    168     int lst = 0;
    169     for (int i = 0; i < n; i++)
    170         if (sa(i) < K + 1)
    171             solve(lst, i), lst = i;
    172     solve(lst, n);
    173     printf(Auto"
    ", res);
    174 }
    175 
    176 int main() {
    177     while (init())
    178         solve();    
    179     return 0;
    180 }
  • 相关阅读:
    【springboot】处理【跨域】请求
    【JPA】【概念】JPA概念解析:CascadeType(各种级联操作)详解
    【JPA】关于SpringBoot使用JPA的更新操作(save方法和原生SQL方法)
    jpa @query上使用if判断
    【Jpa】动态多表if多条件联合查询,并对查询结果进行分页
    phpstorm2020.1 免注册
    uniapp实现多语言切换
    vue进页面input自动获取焦点
    vue-cli4使用less全局变量
    用js实现隐藏手机号中间四位
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9762944.html
Copyright © 2011-2022 走看看