【BZOJ1396】识别子串

题面

http://darkbzoj.tk/problem/1396

题解

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define ri register int
#define N 500050
using namespace std;
vector<int> son[N<<1];
int n;
int sum[N],ans[N];

struct Segment_tree{
  int minv[N<<2];
  void clear() {
    for (ri i=1;i<=4*n;i++) minv[i]=n;
  }
  void pushdown(int x) {
    if (minv[x]<minv[x<<1]) minv[x<<1]=minv[x];
    if (minv[x]<minv[x<<1|1]) minv[x<<1|1]=minv[x];
  }
  int query(int x,int lb,int rb,int loc) {
    if (lb==rb) return minv[x];
    pushdown(x);
    int mid=(lb+rb)/2;
    if (loc<=mid) return query(x<<1,lb,mid,loc); else return query(x<<1|1,mid+1,rb,loc);
  }
  void change(int x,int lb,int rb,int l,int r,int k){
    if (r<lb || l>rb) return;
    if (l<=lb && rb<=r) {
      minv[x]=min(k,minv[x]);
      return;
    }
    pushdown(x);
    int mid=(lb+rb)/2;
    change(x<<1,lb,mid,l,r,k); change(x<<1|1,mid+1,rb,l,r,k);
  }
} t;

struct SAM {
  int ff[N<<1],len[N<<1],cnt[N<<1];
  int ch[N<<1][26];
  int loc[N<<1];
  int las,tot;
  void init() {
    las=tot=1;
  }
  void extend(int c,int la) {
    int np=++tot,p=las; las=tot;
    len[np]=len[p]+1; cnt[np]=1; loc[np]=la;
    while (p && !ch[p][c]) ch[p][c]=np,p=ff[p];
    if (!p) ff[np]=1;
    else {
      int q=ch[p][c];
      if (len[q]==len[p]+1) ff[np]=q;
      else {
        int nq=++tot;
        for (ri i=0;i<26;i++) ch[nq][i]=ch[q][i]; ff[nq]=ff[q];
        len[nq]=len[p]+1;
        ff[np]=ff[q]=nq;
        while (p && ch[p][c]==q) ch[p][c]=nq,p=ff[p];
      }
    }
  }
  
  void maketree(){
    for (ri i=1;i<=tot;i++) son[ff[i]].push_back(i);
  }
  void treesum(int x){
    for (ri i=0;i<son[x].size();i++) {
      treesum(son[x][i]);
      if (cnt[son[x][i]]) loc[x]=loc[son[x][i]];
      cnt[x]+=cnt[son[x][i]];
    }
  }
  void work(){
    for (ri i=1;i<=tot;i++) if (cnt[i]==1) {
      t.change(1,1,n,loc[i]-len[ff[i]],loc[i],len[ff[i]]+1);
      sum[loc[i]-len[ff[i]]-1]++; sum[loc[i]-len[i]]--;
    }
  }
} sam;
char s[N];

int main(){
  sam.init();
  scanf("%s",s);
  n=strlen(s);
  for (ri i=0;i<n;i++) {
    sam.extend(s[i]-'a',i+1);
  }
  sam.maketree();
  sam.treesum(1);
  t.clear();
  sam.work();
  for (ri i=1;i<=n;i++) {
    ans[i]=t.query(1,1,n,i);
  }
  for (ri i=n;i>=1;i--) {
    sum[i]+=sum[i+1];
    if (sum[i]>0) {
      ans[i]=min(ans[i],ans[i+1]+1);
    }
  }
  for (ri i=1;i<=n;i++) printf("%d\n",ans[i]);
}

 

posted @ 2019-07-31 21:50  HellPix  阅读(150)  评论(0编辑  收藏  举报