zoukankan      html  css  js  c++  java
  • BZOJ1396:识别子串(SAM)

    Description

    Input

    一行,一个由小写字母组成的字符串S,长度不超过10^5

    Output

    L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长.

    Sample Input

    agoodcookcooksgoodfood

    Sample Output

    1
    2
    3
    3
    2
    2
    3
    3
    2
    2
    3
    3
    2
    1
    2
    3
    3
    2
    1
    2
    3
    4

    Solution

    1A挺开心的省得调了
    对于SAM上的每一个节点,我们只需要考虑right集合大小为1的
    设一个right集合大小为1的点结束点在endpos,有效长度为[l,r]
    那么对于区间[endpos-r+1,endpos-l+1],这个点的贡献为endpos-i+1,用一颗线段树维护endpos+1,i最后计算贡献
    对于区间[endpos-l+1,endpos],这个点的贡献为l,再开一颗线段树维护l
    最后扫一遍单点查询最小值就好了
    标记永久化好像非常短还好写= =

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N (200000+1000)
     5 using namespace std;
     6 
     7 char s[N];
     8 int Ans,n;
     9 
    10 struct SGT
    11 {
    12     int Segt[N<<1];
    13     SGT(){memset(Segt,0x7f,sizeof(Segt));}
    14     
    15     void Update(int now,int l,int r,int l1,int r1,int k)
    16     {
    17         if (r<l1 || l>r1) return;
    18         if (l1<=l && r<=r1){Segt[now]=min(Segt[now],k);return;}
    19         int mid=(l+r)>>1;
    20         Update(now<<1,l,mid,l1,r1,k); Update(now<<1|1,mid+1,r,l1,r1,k);
    21     }
    22     void Query(int now,int l,int r,int x)
    23     {
    24         Ans=min(Ans,Segt[now]);
    25         if (l==r) return;
    26         int mid=(l+r)>>1;
    27         if (x<=mid) Query(now<<1,l,mid,x);
    28         else Query(now<<1|1,mid+1,r,x);
    29     }
    30 }SGT[2];
    31 
    32 struct SAM
    33 {
    34     int fa[N],son[N][28],right[N],step[N],End[N],od[N],wt[N];
    35     int p,q,np,nq,last,cnt;
    36     SAM(){last=++cnt;}
    37     
    38     void Insert(int x,int pos)
    39     {
    40         p=last; last=np=++cnt; step[np]=step[p]+1; right[np]=1; End[np]=pos;
    41         while (p && !son[p][x]) son[p][x]=np,p=fa[p];
    42         if (!p) fa[np]=1;
    43         else
    44         {
    45             q=son[p][x];
    46             if (step[p]+1==step[q]) fa[np]=q;
    47             else
    48             {
    49                 nq=++cnt; step[nq]=step[p]+1;
    50                 memcpy(son[nq],son[q],sizeof(son[q]));
    51                 fa[nq]=fa[q]; fa[q]=fa[np]=nq;
    52                 while (son[p][x]==q) son[p][x]=nq,p=fa[p];
    53             }
    54         }
    55     }
    56     void Init()
    57     {
    58         int len=strlen(s+1);
    59         for (int i=1; i<=cnt; ++i) wt[step[i]]++;
    60         for (int i=1; i<=len; ++i) wt[i]+=wt[i-1];
    61         for (int i=cnt; i>=1; --i) od[wt[step[i]]--]=i;
    62         for (int i=cnt; i>=1; --i) right[fa[od[i]]]+=right[od[i]];
    63     }
    64     void Solve()
    65     {
    66         for (int i=1; i<=cnt; ++i)
    67         if (right[i]==1)
    68         {
    69             SGT[0].Update(1,1,n,End[i]-step[i]+1,End[i]-step[fa[i]],End[i]+1);
    70             SGT[1].Update(1,1,n,End[i]-step[fa[i]],End[i],step[fa[i]]+1);
    71         }
    72         for (int i=1; i<=n; ++i)
    73         {
    74             Ans=0x7fffffff;
    75             SGT[0].Query(1,1,n,i); Ans-=i;
    76             SGT[1].Query(1,1,n,i);
    77             printf("%d
    ",Ans);
    78         }
    79     }
    80 }SAM;
    81 
    82 int main()
    83 {
    84     scanf("%s",s+1);
    85     n=strlen(s+1);
    86     for (int i=1; i<=n; ++i)
    87         SAM.Insert(s[i]-'a',i);
    88     SAM.Init();
    89     SAM.Solve();
    90 }
  • 相关阅读:
    输入输出重定向
    Tkinter程序屏幕居中
    从Web Controls到DHTML学习随想
    一个没暂时没有办法实现的问题和一个有意思的小问题!
    [学习笔记]几个英语短句(1)
    [读书笔记]My LifeBill Clinton
    [学习笔记]几个英语短句(2)
    结合MS Web Controls做文件上传的解决方案!
    IIS的一个莫名错误--Server Application Unavailable
    Google Sitemaps(测试版)帮助:使用 Sitemap 协议
  • 原文地址:https://www.cnblogs.com/refun/p/9370482.html
Copyright © 2011-2022 走看看