• 【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
    ",ans[i]);
    }
  • 相关阅读:
    [Android]Android开发艺术探索第13章笔记
    [Android]Android性能优化
    [设计模式]单例模式
    [设计模式]享元模式
    [Android]《Android艺术开发探索》第一章读书笔记
    1.传入:”Welome to Beijing”改为 “Beijing to Welcome” 将字符串按照单词进行逆序,空格作为划分单词的唯一条件
    关于ubuntu.18.04的安装注意事项
    String和Date,Timestamp之间的转换
    判断图片色彩模式 CYMK || RGB
    java copy file
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11279321.html
Copyright © 2020-2023  润新知