zoukankan      html  css  js  c++  java
  • bzoj1396 识别子串

    题解:

    首先我们知道对于size==1的点是只出现一次的

    存疑:为什么新增点不会size==1

    那么问题就变成区间取等差数列,区间取最小值

    分别线段树维护就可以了

    代码:

    #include <bits/stdc++.h>
    #define IL inline
    #define ll long long
    #define rint register int
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    using namespace std;
    const int INF=1e9;
    const int N=3e5;
    char s[N];
    int size[N],len[N],ch[N][26];
    int lst=1,node=1,t[N],a[N],fa[N],pos[N],pl;
    void extend(int c)
    {
      int f=lst;
      if (ch[f][c]&&len[ch[f][c]]==len[f]+1)
      { 
        lst=ch[f][c];
        return;
      }
      int p=++node; lst=p;
      len[p]=len[f]+1; //size[p][pl]=1;
      while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f];
      if (!f) { fa[p]=1; return;};
      int x=ch[f][c],y=++node;
      if (len[f]+1==len[x]) {fa[p]=x; node--;return;};
      len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y;
      memcpy(ch[y],ch[x],sizeof(ch[x]));
      while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];
    }
    IL int min(int x,int y)
    {
      if (x>y) return(y); else return(x);
    }
    IL int max(int x,int y)
    {
      if (x<y) return(y); else return(x);
    }
    IL void minn(int &x,int y)
    {
      if (x>y) x=y;
    }
    IL void maxn(int &x,int y)
    {
      if (x<y) x=y;
    }
    const int N1=N*4;
    struct sgt{
      int lazy1[N1],lazy2[N1];
      sgt()
      {
        rep(i,0,N1-1) lazy1[i]=lazy2[i]=INF;
      }
      #define mid ((h+t)/2)
      IL void down(int x,int h,int t)
      {
        minn(lazy1[x*2],lazy1[x]);
        minn(lazy1[x*2+1],lazy1[x]-(mid-h+1));
        minn(lazy2[x*2],lazy2[x]);
        minn(lazy2[x*2+1],lazy2[x]);
      }
      void change1(int x,int h,int t,int h1,int t1,int k)
      {
        if (h1<=h&&t<=t1)
        {
          minn(lazy1[x],k); return;
        }
        down(x,h,t);
        if (h1<=mid) change1(x*2,h,mid,h1,t1,k);
        if (mid<t1) change1(x*2+1,mid+1,t,h1,t1,k-(mid-h+1));
      }
      void change2(int x,int h,int t,int h1,int t1,int k)
      {
        if (h1<=h&&t<=t1)
        {
          minn(lazy2[x],k); return;
        }
        down(x,h,t);
        if (h1<=mid) change2(x*2,h,mid,h1,t1,k);
        if (mid<t1) change2(x*2+1,mid+1,t,h1,t1,k);
      }
      int query(int x,int h,int t,int pos)
      {
        if (h==t)
        {
          return(min(lazy1[x],lazy2[x]));
        }
        down(x,h,t);
        if (pos<=mid) return(query(x*2,h,mid,pos));
        else return(query(x*2+1,mid+1,t,pos));
      }
    }S;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      cin>>s;
      int l=strlen(s);
      int n=l;
      rep(i,1,l) extend(s[i-1]-'a'),size[lst]++,pos[lst]=i;
      rep(i,1,node) t[len[i]]++;
      rep(i,1,node) t[i]+=t[i-1];
      rep(i,1,node) a[t[len[i]]--]=i;
      dep(i,node,1)
      {
        int x=a[i];
        size[fa[x]]+=size[x];   
      }
      rep(i,1,node)
      if (size[i]==1)
      {
        S.change1(1,1,n,pos[i]-len[i]+1,pos[i]-len[fa[i]],len[i]);
        if (fa[i]) S.change2(1,1,n,pos[i]-len[fa[i]]+1,pos[i],1+len[fa[i]]);
      }
      rep(i,1,n)
        cout<<S.query(1,1,n,i)<<endl;
      return 0; 
    } 
  • 相关阅读:
    [HAOI2015]T2
    bzoj1036:[ZJOI2008]树的统计Count
    苹果树
    poj1151 Atlantis
    1593: [Usaco2008 Feb]Hotel 旅馆
    [JSOI2008]最大数maxnumber
    【HNOI2014】米特运输
    【HNOI2013】数列
    Luogu5221 Product
    【CQOI2014】数三角形
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9366063.html
Copyright © 2011-2022 走看看