• 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 }
  • 相关阅读:
    ASP.NET中如何防范SQL注入式攻击?(转)
    打开D盘时速度奇慢?
    Visual Studio 2008 下载地址
    如何利用XML文件,做为配置参数?
    如何将一个表中的数据INSERT INTO 到另一个表中?
    拖延交货或惹万人诉讼 消费者称戴尔态度恶劣
    NHibernate Linq中Null值排序的解决方法
    NHibernate3剖析:Query篇之NHibernate.Linq标准查询
    Nhibernate出现No row with the given identifier exists问题的产生原因及解决方法
    Nhibernate使用动态Expression的问题解决
  • 原文地址:https://www.cnblogs.com/refun/p/9370482.html
Copyright © 2020-2023  润新知