zoukankan      html  css  js  c++  java
  • [NOI2016]优秀的拆分

    题意

    一串字符串的子串能够被拆分成不重叠的$AABB$($A, B$为该子串的子串)的方案数

    题解

    考虑对子串进行隔离处理,枚举隔离长度$l$

    那么在此隔离长度下若存在子串满足$AABB$,那么它必定横跨两个隔离点,那么此时求出每相邻两个隔离点的最长公共前缀$x$和最长公共后缀$y$(跑两遍$SA$求),那么若$x + y >= l$,那么必定可以构成$AABB$的子串(画下图就知道了),那么再统计数量,找到满足该条件的起始位置和终止位置,用差分就好了

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <vector>
      7 
      8 using namespace std;
      9 
     10 typedef long long LL;
     11 
     12 const int MAXN = 3e04 + 10;
     13 
     14 int T;
     15 
     16 int N;
     17 
     18 struct Suffix_Array {
     19     char Str[MAXN];
     20     int M = 122;
     21     int SA[MAXN]= {0};
     22     int Fir[MAXN]= {0}, Srk[MAXN]= {0};
     23     int buck[MAXN]= {0};
     24     void SA_Requirement () {
     25         M = 122;
     26         for (int i = 1; i <= M; i ++)
     27             buck[i] = 0;
     28         for (int i = 1; i <= N; i ++)
     29             buck[Fir[i] = Str[i]] ++;
     30         for (int i = 2; i <= M; i ++)
     31             buck[i] += buck[i - 1];
     32         for (int i = N; i >= 1; i --)
     33             SA[buck[Fir[i]] --] = i;
     34         for (int k = 1; k <= N; k <<= 1) {
     35             int p = 0;
     36             for (int i = N - k + 1; i <= N; i ++)
     37                 Srk[++ p] = i;
     38             for (int i = 1; i <= N; i ++)
     39                 if (SA[i] > k)
     40                     Srk[++ p] = SA[i] - k;
     41             for (int i = 1; i <= M; i ++)
     42                 buck[i] = 0;
     43             for (int i = 1; i <= N; i ++)
     44                 buck[Fir[i]] ++;
     45             for (int i = 2; i <= M; i ++)
     46                 buck[i] += buck[i - 1];
     47             for (int i = N; i >= 1; i --)
     48                 SA[buck[Fir[Srk[i]]] --] = Srk[i], Srk[i] = 0;
     49             swap (Fir, Srk);
     50             Fir[SA[1]] = 1, p = 1;
     51             for (int i = 2; i <= N; i ++)
     52                 Fir[SA[i]] = (Srk[SA[i]] == Srk[SA[i - 1]] && Srk[SA[i] + k] == Srk[SA[i - 1] + k]) ? p : ++ p;
     53             if (p == N)
     54                 break;
     55             M = p;
     56         }
     57     }
     58     int Rank[MAXN]= {0};
     59     int Height[MAXN]= {0};
     60     void Height_Array () {
     61         for (int i = 1; i <= N; i ++)
     62             Rank[SA[i]] = i;
     63         int k = 0;
     64         for (int i = 1; i <= N; i ++) {
     65             if (k)
     66                 k --;
     67             int j = SA[Rank[i] - 1];
     68             while (j + k <= N && i + k <= N && Str[j + k] == Str[i + k])
     69                 k ++;
     70             Height[Rank[i]] = k;
     71         }
     72     }
     73 
     74     int ST[MAXN][20];
     75     void RMQ () {
     76         for (int i = 1; i <= N; i ++)
     77             ST[i][0] = Height[i];
     78         for (int j = 1; j <= 18; j ++)
     79             for (int i = 1; i + (1 << j) - 1 <= N; i ++)
     80                 ST[i][j] = min (ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
     81     }
     82     int Query (int l, int r) {
     83         l ++;
     84         int k = log2 (r - l + 1);
     85         return min (ST[l][k], ST[r - (1 << k) + 1][k]);
     86     }
     87     int LCP (int x, int y) {
     88         if (Rank[x] > Rank[y])
     89             swap (x, y);
     90         return Query (Rank[x], Rank[y]);
     91     }
     92     void init () {
     93         memset (SA, 0, sizeof (SA));
     94         memset (Height, 0, sizeof (Height));
     95         memset (Rank, 0, sizeof (Rank));
     96         memset (Fir, 0, sizeof (Fir));
     97         memset (Srk, 0, sizeof (Srk));
     98     }
     99 } For, Rev;
    100 
    101 int endwith[MAXN]= {0}, startwith[MAXN]= {0};
    102 
    103 int main () {
    104     scanf ("%d", & T);
    105     for (int Case = 1; Case <= T; Case ++) {
    106         memset (endwith, 0, sizeof (endwith));
    107         memset (startwith, 0, sizeof (startwith));
    108         For.init (), Rev.init ();
    109         scanf ("%s", For.Str + 1);
    110         N = strlen (For.Str + 1);
    111         for (int i = 1; i <= N; i ++)
    112             Rev.Str[i] = For.Str[N - i + 1];
    113         For.SA_Requirement (), For.Height_Array (), For.RMQ ();
    114         Rev.SA_Requirement (), Rev.Height_Array (), Rev.RMQ ();
    115         LL ans = 0;
    116         for (int l = 1; l <= (N >> 1); l ++)
    117             for (int i = l, j = (l << 1); j <= N; i += l, j += l) {
    118                 int lcpfor = min (For.LCP (i, j), l);
    119                 int lcprev = min (Rev.LCP (N - j + 1, N - i + 1), l);
    120                 if (lcpfor + lcprev - 1 >= l) {
    121                     endwith[j + l - lcprev] ++;
    122                     endwith[j + lcpfor] --;
    123                     startwith[i - lcprev + 1] ++;
    124                     startwith[i - (l - lcpfor - 1)] --;
    125                 }
    126             }
    127         for (int i = 1; i <= N; i ++) {
    128             endwith[i] += endwith[i - 1];
    129             startwith[i] += startwith[i - 1];
    130         }
    131         for (int i = 1; i <= N; i ++)
    132             ans += (LL) endwith[i] * startwith[i + 1];
    133         printf ("%lld
    ", ans);
    134     }
    135 
    136     return 0;
    137 }
    138 
    139 /*
    140 4
    141 aabbbb
    142 cccccc
    143 aabaabaabaa
    144 bbaabaababaaba
    145 */
    146 
    147 /*
    148 1
    149 aabbbb
    150 */
    151 
    152 /*
    153 10
    154 zzzzzzzzzzzzzzzzzzzzzzzzzzz
    155 icicicicicicicicicicic
    156 saasaasaasaasaasaasaa
    157 znunznunznunznunznun
    158 ttfhhttfhhttfhhttfhhttfhh
    159 fqxqblfqxqblfqxqblfqxqblfqxqbl
    160 xxpruxxpruxxpruxxpru
    161 mpheqsmpheqsmpheqsmpheqs
    162 ptvbemqptvbemqptvbemqptvbemq
    163 nxykqknxykqknxykqknxykqk
    164 */
    165 
    166 /*
    167 1
    168 mpheqsmpheqsmpheqsmpheqs
    169 */
    View Code
  • 相关阅读:
    stenciljs 学习四 组件装饰器
    stenciljs 学习三 组件生命周期
    stenciljs 学习二 pwa 简单应用开发
    stenciljs ionic 团队开发的方便web 组件框架
    stenciljs 学习一 web 组件开发
    使用npm init快速创建web 应用
    adnanh webhook 框架 hook rule
    adnanh webhook 框架 hook 定义
    adnanh webhook 框架request values 说明
    adnanh webhook 框架execute-command 以及参数传递处理
  • 原文地址:https://www.cnblogs.com/Colythme/p/10081744.html
Copyright © 2011-2022 走看看