zoukankan      html  css  js  c++  java
  • 【BZOJ1396】识别子串(后缀自动机,线段树)

    题意:

     一行,一个由小写字母组成的字符串S,长度不超过10^5

    思路:论文题

     设p为自动机上的合法结点,r为右端点,len=st[fa[p]]]+1

    位置[r-st[p]+1,r-len+1]与r-i+1取min,其中i为下标

    位置[r-len+1,r]与len取min

    建立两棵线段树,分别维护r+1和len

    因为只有区间修改和单点查询可以不写lazytag

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef pair<int,int> PII;
      7 typedef pair<ll,ll> Pll;
      8 typedef vector<int> VI;
      9 typedef vector<PII> VII;
     10 typedef pair<ll,int>P;
     11 #define N  100010
     12 #define M  210000
     13 #define fi first
     14 #define se second
     15 #define MP make_pair
     16 #define pi acos(-1)
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     20 #define lowbit(x) x&(-x)
     21 #define Rand (rand()*(1<<16)+rand())
     22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     23 #define ls p<<1
     24 #define rs p<<1|1
     25 
     26 const int MOD=1e9+7,inv2=(MOD+1)/2;
     27       double eps=1e-6;
     28       int INF=1e9;
     29       ll inf=5e13;
     30       int dx[4]={-1,1,0,0};
     31       int dy[4]={0,0,-1,1};
     32 
     33 char s[N];
     34 int p,np,q,nq,k,cas,n;
     35 int t[N<<2][2];
     36 
     37 int read()
     38 {
     39    int v=0,f=1;
     40    char c=getchar();
     41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     43    return v*f;
     44 }
     45 
     46 void build(int l,int r,int p,int op)
     47 {
     48     t[p][op]=INF;
     49     if(l==r) return;
     50     int mid=(l+r)>>1;
     51     build(l,mid,ls,op);
     52     build(mid+1,r,rs,op);
     53 }
     54 
     55 void update(int l,int r,int x,int y,int v,int p,int op)
     56 {
     57     if(x<=l&&r<=y)
     58     {
     59         t[p][op]=min(t[p][op],v);
     60         return;
     61     }
     62     int mid=(l+r)>>1;
     63     if(x<=mid) update(l,mid,x,y,v,ls,op);
     64     if(y>mid) update(mid+1,r,x,y,v,rs,op);
     65 }
     66 
     67 int query(int l,int r,int x,int p,int op)
     68 {
     69     if(l==r) return t[p][op];
     70     int mid=(l+r)>>1;
     71     if(x<=mid) return min(t[p][op],query(l,mid,x,ls,op));
     72      else return min(t[p][op],query(mid+1,r,x,rs,op));
     73 }
     74 
     75 struct sam
     76 {
     77     int cnt;
     78     int fa[N<<1],ch[N<<1][26];
     79     int st[N<<1],b[N<<1],bl[N<<1],to[N<<1],size[N<<1];
     80 
     81     sam()
     82     {
     83         cnt=np=1;
     84     }
     85 
     86     void add(int x,int i)
     87     {
     88         p=np; st[np=++cnt]=st[p]+1;
     89         to[np]=i;
     90         while(p&&!ch[p][x])
     91         {
     92             ch[p][x]=np;
     93             p=fa[p];
     94         }
     95         if(!p) fa[np]=1;
     96          else if(st[p]+1==st[q=ch[p][x]]) fa[np]=q;
     97           else
     98           {
     99                   st[nq=++cnt]=st[p]+1;
    100                   memcpy(ch[nq],ch[q],sizeof ch[q]);
    101                   //t[nq]=t[q];
    102                   fa[nq]=fa[q];
    103                   fa[q]=fa[np]=nq;
    104                   while(p&&ch[p][x]==q)
    105                   {
    106                       ch[p][x]=nq;
    107                       p=fa[p];
    108                   }
    109           }
    110     }
    111 
    112     void solve()
    113     {
    114         rep(i,1,cnt) b[st[i]]++;
    115         rep(i,1,cnt) b[i]+=b[i-1];
    116         rep(i,1,cnt) bl[b[st[i]]--]=i;
    117         int u=1;
    118         rep(i,1,n)
    119         {
    120             u=ch[u][s[i]-'a'];
    121             size[u]++;
    122         }
    123         build(1,n,1,0);
    124         build(1,n,1,1);
    125         per(i,cnt,1) size[fa[bl[i]]]+=size[bl[i]];
    126 
    127         rep(i,1,cnt)
    128         {
    129             int p=bl[i];
    130             if(size[p]>1) continue;
    131             int len=st[fa[p]]+1,r=to[p];
    132             update(1,n,r-len+1,r,len,1,0);
    133             update(1,n,r-st[p]+1,r-len+1,r+1,1,1);
    134         }
    135 
    136         rep(i,1,n)
    137         {
    138             int t1=query(1,n,i,1,0),t2=-i+query(1,n,i,1,1);
    139             printf("%d
    ",min(t1,t2));
    140         }
    141 
    142     }
    143 }sam;
    144 
    145 
    146 int main()
    147 {
    148     scanf("%s",s+1);
    149     n=strlen(s+1);
    150     rep(i,1,n) sam.add(s[i]-'a',i);
    151     sam.solve();
    152     return 0;
    153 }
  • 相关阅读:
    IBM小练习
    面向对象
    面向对象_人狗大战
    面向对象组合小练习
    面向对象小作业
    作业大礼包_员工信息表
    异常报错处理
    开发规范

    U-boot工作流程分析
  • 原文地址:https://www.cnblogs.com/myx12345/p/11507540.html
Copyright © 2011-2022 走看看