zoukankan      html  css  js  c++  java
  • bzoj1396&&2865 识别子串 后缀自动机+线段树

    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数上的叶子节点,endpos=1
    所以只需要找endpos=1的节点minlen-maxlen之间对于一段的贡献放向去思考就可以了。
     

    理解起来就是对于[endposmaxlen+1,endposminlen+1][endpos−maxlen+1,endpos−minlen+1]中的每个子串都是单独存在的,所以这个RightRight集合贡献给他的答案就是这个点到endposendpos的长度。

    对于[endposminlen,endpos][endpos−minlen,endpos]中的每个位置xx,贡献就是minlenminlen;

    理解起来就是对于[endposminlen,endpos][endpos−minlen,endpos]中的每个子串显然是存在多个结束位置的,所以当前这个RightRight集合能够贡献给他的符合只出现一次且最短的,就是刚好跨过它的最小,即minlenminlen。

    对于2865数据范围大了,而且还卡内存,不要面孔

    纯自己手打

      1 #pragma GCC optimize(2)
      2 #pragma G++ optimize(2)
      3 #include<cstring>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<cstdio>
      8 
      9 #define inf 1000000007
     10 #define N 200007
     11 using namespace std;
     12 inline int read()
     13 {
     14     int x=0,f=1;char ch=getchar();
     15     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     16     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 
     20 int n;
     21 char ch[N];
     22 
     23 struct segment_tree
     24 {
     25     int tree[N<<2];
     26     inline void push_down(int p,int l,int r)
     27     {
     28         if(l==r)return;
     29         int ls=p<<1,rs=p<<1|1;
     30         tree[ls]=min(tree[ls],tree[p]);
     31         tree[rs]=min(tree[rs],tree[p]);
     32     }
     33     void update(int p,int l,int r,int x,int y,int num)
     34     {
     35         if(x>y)return;
     36         push_down(p,l,r);
     37         if(l==x&&y==r)
     38         {
     39             tree[p]=min(tree[p],num);
     40             return;
     41         }
     42         int mid=(l+r)>>1;
     43         if(y<=mid)update(p<<1,l,mid,x,y,num);
     44         else if(x>mid)update(p<<1|1,mid+1,r,x,y,num);
     45         else update(p<<1,l,mid,x,mid,num),update(p<<1|1,mid+1,r,mid+1,y,num);
     46     }
     47     void build(int p,int l,int r)
     48     {
     49         if(l==r)
     50         {
     51             tree[p]=inf;
     52             return;
     53         }
     54         int mid=(l+r)>>1;
     55         build(p<<1,l,mid),build(p<<1|1,mid+1,r);
     56         tree[p]=inf;
     57     }
     58     int query(int p,int l,int r,int x)
     59     {
     60         push_down(p,l,r);
     61         if(l==r)return tree[p];
     62         int mid=(l+r)>>1;
     63         if(x<=mid) return query(p<<1,l,mid,x);
     64         else return query(p<<1|1,mid+1,r,x);
     65     }
     66 }A,B;
     67 struct sam
     68 {
     69     int last,cnt,rt;
     70     int fa[N],mx[N],c[N][26];
     71     sam(){last=cnt=rt=1;}
     72     void extend(int x)
     73     {
     74         int p=last,np=last=++cnt;mx[np]=mx[p]+1;
     75         while(p&&!c[p][x])
     76         {
     77             c[p][x]=np;
     78             p=fa[p];
     79         }
     80         if(!p)fa[np]=rt;
     81         else
     82         {
     83             int q=c[p][x];
     84             if(mx[q]==mx[p]+1)fa[np]=q;
     85             else
     86             {
     87                 int nq=++cnt;mx[nq]=mx[p]+1;
     88                 memcpy(c[nq],c[q],sizeof(c[q]));
     89                 fa[nq]=fa[q];
     90                 fa[q]=fa[np]=nq;
     91                 while(c[p][x]==q)c[p][x]=nq,p=fa[p];
     92             }
     93         }
     94     }
     95     bool flag[N];
     96     void build()
     97     {
     98         memset(flag,true,sizeof(flag));
     99         for (int i=1;i<=cnt;i++)
    100             flag[fa[i]]=false;
    101         for (int i=1;i<=cnt;i++)
    102             if(flag[i])
    103             {
    104                 int l=mx[i]-mx[fa[i]],r=mx[i];
    105                 A.update(1,1,n,1,l-1,r+1);
    106                 B.update(1,1,n,l,r,r-l+1);
    107             }
    108     }
    109 }sam;
    110 void solve()
    111 {
    112     for (int i=1;i<=n;i++)
    113         printf("%d
    ",min(A.query(1,1,n,i)-i,B.query(1,1,n,i)));
    114 }
    115 int main()
    116 {
    117     freopen("fzy.in","r",stdin);
    118     freopen("fzy.out","w",stdout);
    119     scanf("%s",ch+1);n=strlen(ch+1);
    120     for (int i=1;i<=n;i++)
    121         sam.extend(ch[i]-'a');
    122     A.build(1,1,n),B.build(1,1,n);
    123 //    cout<<1<<endl<<endl;
    124     sam.build(),solve();
    125 }
  • 相关阅读:
    670. Maximum Swap
    653. Two Sum IV
    639. Decode Ways II
    636. Exclusive Time of Functions
    621. Task Scheduler
    572. Subtree of Another Tree
    554. Brick Wall
    543. Diameter of Binary Tree
    535. Encode and Decode TinyURL
    博客园自定义背景图片
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8530667.html
Copyright © 2011-2022 走看看