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\n",std::min(ans1,ans2));
164     }
165     return 0;
166 }

 

posted @ 2018-11-28 22:39  Unstoppable728  阅读(245)  评论(0编辑  收藏  举报