zoukankan      html  css  js  c++  java
  • [NOI2018]你的名字

    主要题意

    求字符串$S$与$T$不同的子串总数

    题解

    先考虑$l = 1, r = |T|$的情况:

    因为任意子串为字符串前缀的某些后缀,那么令$Lim[i]$表示$T[1...i]$在$S$上所能匹配的最大长度,$Posi[i]$表示$T$的后缀自动机上的点$i$的$endpos$集合中最靠前的位置,那么答案即为

    $$Ans = sumlimits_{i = 1}^{nodes} max (0, Len[i] - min (Len[Father[i]], Lim[Posi[i]]))$$

    接下来考虑$l, r$任意的情况:

    原来能否在$S$的后缀自动机上往下走的判断依据只有当前节点是否存在$c$边,那么有了$l, r$的限制,就多需要判断向下的这个节点的$endpos$是否有存在于$[l + len, r]$($len$表示已匹配长度)区间的位置,$endpos$集合用动态开点线段树维护一下就好了

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 
      5 using namespace std;
      6 
      7 typedef long long LL;
      8 
      9 const int MAXN = 2e06 + 10;
     10 const int MAXL = 20 + 5;
     11 
     12 const int INF = 0x7fffffff;
     13 
     14 int N, M, Q;
     15 char Orig[MAXN], Str[MAXN];
     16 
     17 int Root[MAXN]= {0};
     18 int Left[MAXN * MAXL]= {0}, Right[MAXN * MAXL]= {0};
     19 int tnodes = 0;
     20 void Modify (int& root, int left, int right, int pos) {
     21     if (! root)
     22         root = ++ tnodes;
     23     if (left == right)
     24         return ;
     25     int mid = (left + right) >> 1;
     26     pos <= mid ? Modify (Left[root], left, mid, pos) : Modify (Right[root], mid + 1, right, pos);
     27 }
     28 int Tree_Merge (int sl, int sr) {
     29     if (! sl || ! sr)
     30         return sl + sr;
     31     int p = ++ tnodes;
     32     Left[p] = Tree_Merge (Left[sl], Left[sr]);
     33     Right[p] = Tree_Merge (Right[sl], Right[sr]);
     34     return p;
     35 }
     36 bool Query (int root, int left, int right, int L, int R) {
     37     if (! root || left > right)
     38         return false;
     39     if (L <= left && right <= R)
     40         return true;
     41     int mid = (left + right) >> 1;
     42     if (L <= mid)
     43         if (Query (Left[root], left, mid, L, R))
     44             return true;
     45     if (R > mid)
     46         if (Query (Right[root], mid + 1, right, L, R))
     47             return true;
     48     return false;
     49 }
     50 
     51 struct SAM {
     52     int Tree[MAXN][30];
     53     int Father[MAXN];
     54     int Len[MAXN], Posi[MAXN];
     55     int last, nodes;
     56 
     57     void init () {
     58         for (int i = 1; i <= nodes; i ++) {
     59             memset (Tree[i], 0, sizeof (Tree[i]));
     60             Father[i] = 0, Posi[i] = 0;
     61         }
     62         last = nodes = 1;
     63     }
     64 
     65     void Append (int c, int pos, int type) {
     66         int fa = last, p = ++ nodes;
     67         last = p;
     68         Len[p] = Len[fa] + 1, Posi[p] = pos;
     69         while (fa && ! Tree[fa][c])
     70             Tree[fa][c] = p, fa = Father[fa];
     71         if (! fa)
     72             Father[p] = 1;
     73         else {
     74             int x = Tree[fa][c];
     75             if (Len[x] == Len[fa] + 1)
     76                 Father[p] = x;
     77             else {
     78                 int np = ++ nodes;
     79                 Len[np] = Len[fa] + 1, Father[np] = Father[x], Posi[np] = Posi[x];
     80                 Father[p] = Father[x] = np;
     81                 memcpy (Tree[np], Tree[x], sizeof (Tree[x]));
     82                 while (fa && Tree[fa][c] == x)
     83                     Tree[fa][c] = np, fa = Father[fa];
     84             }
     85         }
     86         if (type == 1)
     87             Modify (Root[p], 1, N, pos);
     88     }
     89     int Topo[MAXN];
     90     int Minp[MAXN];
     91     int buck[MAXN];
     92     /*void Merge_Minp () {
     93         for (int i = 1; i <= nodes; i ++)
     94             buck[i] = 0, Minp[i] = Posi[i];
     95         for (int i = 1; i <= nodes; i ++)
     96             buck[Len[i]] ++;
     97         for (int i = 1; i <= N; i ++)
     98             buck[i] += buck[i - 1];
     99         for (int i = nodes; i >= 1; i --)
    100             Topo[buck[Len[i]] --] = i;
    101         for (int i = nodes; i >= 1; i --)
    102             Minp[Father[Topo[i]]] = min (Minp[Father[Topo[i]]], Minp[Topo[i]]);
    103     }*/
    104     void Merge_Tree () {
    105         for (int i = 1; i <= nodes; i ++)
    106             buck[i] = 0;
    107         for (int i = 1; i <= nodes; i ++)
    108             buck[Len[i]] ++;
    109         for (int i = 1; i <= N; i ++)
    110             buck[i] += buck[i - 1];
    111         for (int i = nodes; i >= 1; i --)
    112             Topo[buck[Len[i]] --] = i;
    113         for (int i = nodes; i >= 1; i --)
    114             Root[Father[Topo[i]]] = Tree_Merge (Root[Father[Topo[i]]], Root[Topo[i]]);
    115     }
    116 } ;
    117 SAM S, T;
    118 
    119 int Lim[MAXN]= {0};
    120 /*void Match (int l, int r) {
    121     int p = 1, len = 0;
    122     for (int i = 1; i <= M; i ++) {
    123         int c = Str[i] - 'a';
    124         while (p && ! S.Tree[p][c])
    125             p = S.Father[p], len = S.Len[p];
    126         while (p && ! Query (Root[S.Tree[p][c]], 1, N, l + len, r))
    127             p = S.Father[p], len = S.Len[p];
    128         S.Tree[p][c] ? (p = S.Tree[p][c], len ++) : (p = 1, len = 0);
    129         Lim[i] = len;
    130     }
    131 }*/
    132 void Work (int l, int r) {
    133     int p = 1, len = 0;
    134     for (int j = 1; j <= M; j ++) {
    135         int c = Str[j] - 'a';
    136         T.Append (c, j, 2);
    137         while (true) {
    138             if (S.Tree[p][c] && Query (Root[S.Tree[p][c]], 1, N, l + len, r)) {
    139                 p = S.Tree[p][c], len ++;
    140                 break;
    141             }
    142             if (! len)
    143                 break;
    144             len --;
    145             if (len == S.Len[S.Father[p]])
    146                 p = S.Father[p];
    147         }
    148         Lim[j] = len;
    149     }
    150     // T.Merge_Minp ();
    151     // Match (l, r);
    152 }
    153 
    154 LL Solve () {
    155     LL ans = 0;
    156     for (int i = 1; i <= T.nodes; i ++)
    157         ans += max (0, T.Len[i] - max (T.Len[T.Father[i]], Lim[T.Posi[i]]));
    158     return ans;
    159 }
    160 
    161 int getnum () {
    162     int num = 0;
    163     char ch = getchar ();
    164 
    165     while (! isdigit (ch))
    166         ch = getchar ();
    167     while (isdigit (ch))
    168         num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();
    169 
    170     return num;
    171 }
    172 
    173 int main () {
    174     scanf ("%s", Orig + 1);
    175     N = strlen (Orig + 1);
    176     S.init ();
    177     for (int i = 1; i <= N; i ++)
    178         S.Append (Orig[i] - 'a', i, 1);
    179     S.Merge_Tree ();
    180     scanf ("%d", & Q);
    181     for (int i = 1; i <= Q; i ++) {
    182         scanf ("%s", Str + 1);
    183         int l = getnum (), r = getnum ();
    184         T.init ();
    185         M = strlen (Str + 1);
    186         Work (l, r);
    187         LL ans = Solve ();
    188         printf ("%lld
    ", ans);
    189     }
    190 
    191     return 0;
    192 }
    193 
    194 /*
    195 scbamgepe
    196 3
    197 smape 1 9
    198 sbape 1 9
    199 sgepe 1 9
    200 */
    201 
    202 /*
    203 scbamgepe
    204 3
    205 smape 2 7
    206 sbape 3 8
    207 sgepe 1 9
    208 */
    View Code
  • 相关阅读:
    CDH 2、Cloudera Manager的安装
    204 01 Android 零基础入门 03 Java常用工具类 04 Java集合 04 Map集合 01 Map概述
    203 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 07 删除宠物猫信息数据(引入泛型知识点)
    202 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 06 查找宠物猫信息数据
    201 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 05 添加重复的宠物猫信息数据
    200 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 04 添加和显式宠物猫信息
    199 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 03 宠物猫信息管理概述
    198 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 02 案例:在集合中插入字符串
    197 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 01 Set概述
    196 01 Android 零基础入门 03 Java常用工具类 04 Java集合 02 List集合 05 案例:公告的删除和修改
  • 原文地址:https://www.cnblogs.com/Colythme/p/10109277.html
Copyright © 2011-2022 走看看