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 }
  • 相关阅读:
    Cookie同Session的关系 (2)
    Java Web应用开发概述
    Oracle客户端工具连接数据库服务器问题汇总
    java中使用JSCH包,SFTP及SSH2文件操作及远程命令执行
    javascript学习实录 之九(选择样式,改变文字效果) 刘小小尘
    用python给MP3加封面图片,修改作者,专辑等信息
    超像素分割技术发展情况梳理(Superpixel Segmentation)计算机视觉专题3
    android 应用程序的内存分析
    查询成绩
    sharepoint 2010 获取列表术语数据源方法
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8530667.html
Copyright © 2011-2022 走看看