zoukankan      html  css  js  c++  java
  • 【SDOI2016】生成魔咒

    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 次操作加入的魔咒字符。 
    1≤n≤100000。,用来表示魔咒字符的数字 x 满足 1≤x≤10^9

    Output

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

    Sample Input


    1 2 3 3 3 1 2

    Sample Output





    12 
    17 
    22

    Hint

    数据约束: 
    对于 10% 的数据,1≤n≤10。 
    对于 30% 的数据,1≤n≤100。 
    对于 60% 的数据,1≤n≤1000。 
    对于 100% 的数据,1≤n≤100000。 
    用来表示魔咒字符的数字 x 满足 1≤x≤109。

     

    反过来后,每多一个原来的前缀,相当于多一个现在的后缀.
    注意到一个事(tao)实(lu).

    每次新加入的那个后缀与前面加的后缀的lcp一定是前面名次与他最相近的两个后缀与他的lcp的最大值,

    因为名次越近相似度越高.

    所以维护一个set和ST表,每次求出这个值,最终产生的答案就是这个后缀的长度-lcp.


     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<string>
     6 #include<algorithm>
     7 #include<map>
     8 #include<complex>
     9 #include<queue>
    10 #include<stack>
    11 #include<cmath>
    12 #include<set>
    13 #include<vector>
    14 #define LL long long
    15 #define maxn 100010
    16 using namespace std;
    17 int s[maxn],sa[maxn],rk[maxn],tmp[maxn],n,k;
    18 LL lcp[maxn],ans[maxn],f[maxn][21];
    19 set<int>se;
    20 bool cmp(int i,int j){
    21   if(rk[i]!=rk[j]) return rk[i]<rk[j];
    22   else {
    23     int ri=i+k<=n?rk[i+k]:-1,rj=j+k<=n?rk[j+k]:-1;
    24     return ri<rj;
    25   }
    26 }
    27 void get_sa(){
    28   for(int i=0;i<=n;i++)
    29     sa[i]=i,rk[i]=i<n?s[i]:-1;
    30   for(k=1;k<=n;k*=2){
    31     sort(sa,sa+n+1,cmp);
    32     tmp[sa[0]]=0;
    33     for(int i=1;i<=n;i++)
    34       tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0);
    35     for(int i=0;i<=n;i++)
    36       rk[i]=tmp[i];
    37   }
    38 }
    39 void get_lcp(){
    40   for(int i=0;i<=n;i++) rk[sa[i]]=i;
    41   int h=0;lcp[0]=0;
    42   for(int i=0;i<n;i++){
    43     int j=sa[rk[i]-1];
    44     if(h>0) h--;
    45     for(;j+h<n && i+h<n;h++)
    46       if(s[j+h]!=s[i+h]) break;
    47     lcp[rk[i]-1]=h;
    48   }
    49 }
    50 int main(){
    51  // freopen("!.in","r",stdin);
    52  // freopen("!.out","w",stdout);
    53   scanf("%d",&n);
    54   for(int i=n-1;i>=0;i--)
    55     scanf("%d",&s[i]);
    56   get_sa();get_lcp();
    57   for(int i=0;i<=n;i++) f[i][0]=lcp[i];
    58   for(int j=1;j<=18;j++)
    59     for(int i=0;i+(1<<(j-1))<=n;i++)
    60       f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    61   se.insert(rk[n-1]);
    62   ans[n-1]=1;
    63   for(int i=n-2;i>=0;i--){
    64     int lcpa=0,lcpb=0;
    65     se.insert(rk[i]);
    66     set<int>::iterator it=se.find(rk[i]);
    67     if(it!=se.begin()){
    68       it--;
    69       int len=log(rk[i]-*it)/log(2);
    70       if(1<<(len+1)<=rk[i]-*it) len++;
    71       lcpa=min(f[*it][len],f[rk[i]-(1<<len)][len]);
    72       it++;
    73     }
    74     if((++it)!=se.end()){
    75       int len=log(*it-rk[i])/log(2);
    76       if(1<<(len+1)<=rk[i]-*it) len++;
    77       lcpb=min(f[rk[i]][len],f[*it-(1<<len)][len]);
    78     }
    79     ans[i]=n-i-max(lcpa,lcpb);
    80   }
    81   for(int i=n-1;i>=0;i--)
    82     ans[i]+=ans[i+1],printf("%lld
    ",ans[i]);
    83   return 0;
    84 }
    
    
  • 相关阅读:
    微服务架构总结
    微服务-网关服务
    HttpClient-RestTemplate-Feign
    RPC和REST
    Springmvc的拦截器执行顺序及各方法作用
    秒杀系统优化方案(下)吐血整理
    秒杀系统优化方案(上)吐血整理
    分布式session的管理
    缓存设计——缓存和数据库的数据一致性
    个人理解的javascript作用域链与闭包
  • 原文地址:https://www.cnblogs.com/pantakill/p/7197467.html
Copyright © 2011-2022 走看看