• BZOJ1396: 识别子串(后缀自动机,线段树)


    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

    解题思路:

    思考一个最小识别串会带来什么。

    在它内部的点的答案就是这个串的长度,而在它外面的点需要拓展到这个串的端点。

    首先,一个Parent树内的节点对应子串是唯一识别的,那么其|Right|必定=1,那么对应一个|Right|=1的节点

    因为Parent树上的节点是其子节点的后缀,而Parent树是逆序的,所以一棵|Right|=1的子树内结尾是一定的,设为endpos。

    那么在一个|Right|=1的节点内其有效压缩长度为len-len[fa],那么这段子串可以认为是等价唯一的。其长度为其到endpos的距离。

    而在len[fa]以下的,识别长度太小必须使用len[fa]为最小识别长度。

    区间修改当然要线段树了。

    len[fa]~len区间内,其答案为endpos-pos+1

    1~len[fa]区间内,其答案为len[fa]

    pos是与位置有关的变量最后算。

    只需将endpos-1,len[fa]推入线段树好了

    代码:

    (不要问我为什么上次拓扑这次建边因为我闲的)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll spc<<1
      5 #define rrr spc<<1|1
      6 struct sant{
      7     int tranc[26];
      8     int len;
      9     int pre;
     10 }s[1000000];
     11 struct pnt{
     12     int hd;
     13     int wgt;
     14     int endp;
     15 }p[1000000];
     16 struct ent{
     17     int twd;
     18     int lst;
     19 }e[1000000];
     20 struct trnt{
     21     int minval;
     22     int lzt;
     23     bool al;
     24 };
     25 int cnt;
     26 int siz;
     27 int fin;
     28 int n;
     29 char tmp[1000000];
     30 class Sgmt_tree{
     31     public:
     32         void res(void)
     33         {
     34             for(int i=0;i<500000;i++)
     35                 tr[i].lzt=tr[i].minval=0x3f3f3f3f;
     36             return ;
     37         }
     38         void pushup(int spc)
     39         {
     40             tr[spc].minval=std::min(tr[lll].minval,tr[rrr].minval);
     41             return ;
     42         }
     43         void Add(int spc,int x)
     44         {
     45             tr[spc].minval=std::min(tr[spc].minval,x);
     46             tr[spc].lzt=std::min(tr[spc].lzt,x);
     47             tr[spc].al=true;
     48             return ;
     49         }
     50         void pushdown(int spc)
     51         {
     52             if(tr[spc].al)
     53             {
     54                 Add(lll,tr[spc].lzt);
     55                 Add(rrr,tr[spc].lzt);
     56                 tr[spc].al=false;
     57             }
     58             return ;
     59         }
     60         void update(int l,int r,int ll,int rr,int spc,int v)
     61         {
     62             if(l>rr||ll>r)
     63                 return ;
     64             if(ll<=l&&r<=rr)
     65             {
     66                 Add(spc,v);
     67                 return ;
     68             }
     69             int mid=(l+r)>>1;
     70             pushdown(spc);
     71             update(l,mid,ll,rr,lll,v);
     72             update(mid+1,r,ll,rr,rrr,v);
     73             pushup(spc);
     74             return ;
     75         }
     76         int query(int l,int r,int pos,int spc)
     77         {
     78             if(l==r)
     79                 return tr[spc].minval;
     80             int mid=(l+r)>>1;
     81             pushdown(spc);
     82             if(pos<=mid)
     83                 return query(l,mid,pos,lll);
     84             else
     85                 return query(mid+1,r,pos,rrr);
     86         }
     87     private:
     88         trnt tr[500000];
     89 }T[2];
     90 void Insert(int c,int w)
     91 {
     92     int nwp,nwq,lsq,lsp;
     93     nwp=++siz;
     94     p[nwp].wgt=1;
     95     p[nwp].endp=w;
     96     s[nwp].len=s[fin].len+1;
     97     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
     98         s[lsp].tranc[c]=nwp;
     99     if(!s[lsp].tranc[c])
    100         s[lsp].tranc[c]=nwp;
    101     else{
    102         lsq=s[lsp].tranc[c];
    103         if(s[lsq].len==s[lsp].len+1)
    104             s[nwp].pre=lsq;
    105         else{
    106             nwq=++siz;
    107             s[nwq]=s[lsq];
    108             s[nwq].len=s[lsp].len+1;
    109             s[nwp].pre=s[lsq].pre=nwq;
    110             while(s[lsp].tranc[c]==lsq)
    111             {
    112                 s[lsp].tranc[c]=nwq;
    113                 lsp=s[lsp].pre;
    114             }
    115         }
    116     }
    117     fin=nwp;
    118     return ;
    119 }
    120 void ade(int f,int t)
    121 {
    122     cnt++;
    123     e[cnt].twd=t;
    124     e[cnt].lst=p[f].hd;
    125     p[f].hd=cnt;
    126     return ;
    127 }
    128 void Dfs(int x)
    129 {
    130     for(int i=p[x].hd;i;i=e[i].lst)
    131     {
    132         int to=e[i].twd;
    133         Dfs(to);
    134         p[x].wgt+=p[to].wgt;
    135         p[x].endp=std::min(p[x].endp,p[to].endp);
    136     }
    137     if(p[x].wgt==1)
    138     {
    139         int minlen=s[s[x].pre].len+1;
    140         int maxlen=s[x].len;
    141         int endpos=p[x].endp;
    142         T[0].update(1,n,endpos-maxlen+1,endpos-minlen+1,1,endpos+1);
    143         T[1].update(1,n,endpos-minlen+1,endpos,1,minlen);
    144     }
    145     return ;
    146 }
    147 int main()
    148 {
    149     scanf("%s",tmp+1);
    150     n=strlen(tmp+1);
    151     for(int i=1;i<=n;i++)
    152         Insert(tmp[i]-'a',i);
    153     for(int i=1;i<=siz;i++)
    154         ade(s[i].pre,i);
    155     T[0].res();
    156     T[1].res();
    157     Dfs(0);
    158     for(int i=1;i<=n;i++)
    159     {
    160         int ans1,ans2;
    161         ans1=T[0].query(1,n,i,1)-i;
    162         ans2=T[1].query(1,n,i,1);
    163         printf("%d
    ",std::min(ans1,ans2));
    164     }
    165     return 0;
    166 }
  • 相关阅读:
    【poj1182】 食物链
    【bzoj1013】 JSOI2008—球形空间产生器sphere
    【codevs1200】 NOIP2012—同余方程
    【poj2891】 Strange Way to Express Integers
    【bzoj2819】 Nim
    【bzoj2463】 谁能赢呢?
    【poj3537】 Crosses ans Crosses
    【bzoj2115】 Xor
    下载时出现using cached如何解决
    如何设计一个"好的"测试用例?
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10035522.html
Copyright © 2020-2023  润新知