zoukankan      html  css  js  c++  java
  • 【BZOJ4516】【SDOI2016】生成魔咒 [SAM]

    生成魔咒

    Time Limit: 10 Sec  Memory Limit: 128 MB
    [Submit][Status][Discuss]

    Description

      魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。
      一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。
      例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。
      S=[1,1,1] 时,它的生成魔咒有 [1]、[1,1]、[1,1,1] 三种。
      最初 S 为空串。共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符。
      每次操作后都需要求出,当前的魔咒串 S 共有多少种生成魔咒。

    Input

      第一行一个整数 n。
      第二行 n 个数,第 i 个数表示第 i 次操作加入的魔咒字符。

    Output

      输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量

    Sample Input

      7
      1 2 3 3 3 1 2

    Sample Output

      1
      3
      6
      9
      12
      17
      22

    HINT

      1≤n≤100000

    Main idea

      询问在加入每一个字符后当前有多少个本质不同的子串。

    Solution

      直接用SAM,根据SAM的性质,每次增多的子串个数就是len[New] - len[fa[New]]

    Code

     1 #include<iostream>    
     2 #include<string>    
     3 #include<algorithm>    
     4 #include<cstdio>    
     5 #include<cstring>    
     6 #include<cstdlib>
     7 #include<cmath>
     8 #include<map>
     9 using namespace std;  
    10 typedef long long s64;
    11 
    12 const int ONE = 400005;
    13 const int INF = 2147483640;
    14 
    15 int n,x;
    16 s64 Ans;
    17 
    18 int get()
    19 {    
    20         int res=1,Q=1;char c;    
    21         while( (c=getchar())<48 || c>57 ) 
    22         if(c=='-')Q=-1; 
    23         res=c-48;     
    24         while( (c=getchar())>=48 && c<=57 )    
    25         res=res*10+c-48;    
    26         return res*Q;
    27 }
    28 
    29 struct SAM
    30 {
    31         map <int, int> a[ONE];
    32         int len[ONE], fa[ONE];
    33         int last, cnt;
    34         SAM() {last = cnt = 1;}
    35         void Add(int c)
    36         {
    37             int x = last, New = last = ++cnt;
    38             len[New] = len[x] + 1;
    39             while(x && !a[x][c]) a[x][c] = New, x = fa[x];
    40             if(!x) {fa[New] = 1; Ans += len[New] - len[fa[New]]; return;}
    41             
    42             int q = a[x][c];
    43             if(len[x] + 1 == len[q]) fa[New] = q;
    44             else
    45             {
    46                 int Nq = ++cnt;    len[Nq] = len[x] + 1;
    47                 a[Nq] = a[q];
    48                 fa[Nq] = fa[q];
    49                 fa[New] = fa[q] = Nq;
    50                 while(a[x][c] == q) a[x][c] = Nq, x = fa[x];
    51             }
    52             Ans += len[New] - len[fa[New]];
    53         }
    54 }S;
    55 
    56 int main()
    57 {
    58         n = get();
    59         while(n--)
    60         {
    61             x = get();
    62             S.Add(x);
    63             printf("%lld
    ", Ans);
    64         }
    65         
    66 }
    View Code

     

  • 相关阅读:
    HDU-3065-病毒侵袭持续中(AC自动机)
    HDU-2896-病毒侵袭(AC自动机)
    HDU
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) D. Sequence Sorting
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) B. Strings Equalization
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) A. CME
    Codeforces Round #586 (Div. 1 + Div. 2) E. Tourism
    Codeforces Round #586 (Div. 1 + Div. 2) D. Alex and Julian
    jsp内置对象
  • 原文地址:https://www.cnblogs.com/BearChild/p/6915963.html
Copyright © 2011-2022 走看看