【LOJ#6041】事情的相似度

题面

https://loj.ac/problem/6041

题解

两个后缀的$LCS$,就是在后缀树上的$LCA$的深度。对于同属于一个$LCA$的点,我们只需要在原序列上连续的两个(实现上,直接在插进去的时候找就可以了,要是遍历一遍复杂度就假了)

启发式合并。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<set>
#include<algorithm>
#include<vector>
#define ri register int
#define N 100500
using namespace std;

int n,q,cc,ans[N];
char s[N];

struct ques {
  int l,r,id;
  bool operator < (const ques &rhs) const {
    return r<rhs.r || (r==rhs.r && l<rhs.l);
  }
} qu[N];

struct pir{
  int l,r,v;
  bool operator < (const pir &rhs) const {
    return r<rhs.r || (r==rhs.r && l<rhs.l);
  }
} pp[N<<5];

struct SAM{
  int ch[N<<1][2];
  int ff[N<<1],len[N<<1];
  int las,tot;
  vector<int> son[N<<1];
  set<int> endp[N<<1];
  void clear() {
    las=tot=1;
  }
  void extend(int c){
    int p=las,np=++tot; las=tot;
    len[np]=len[p]+1;
    while (p && ch[p][c]==0) 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;
        len[nq]=len[p]+1; ff[nq]=ff[q];
        for (ri i=0;i<2;i++) ch[nq][i]=ch[q][i];
        ff[np]=ff[q]=nq;
        while (p && ch[p][c]==q) ch[p][c]=nq,p=ff[p];
      }
    }
    endp[np].insert(len[np]);
  }
  
  void maketree() {
    for (ri i=1;i<=tot;i++) son[ff[i]].push_back(i);
  }
  void merge(int x) {
    set<int> :: iterator it,it2,itp,itq;
    for (ri i=0;i<son[x].size();i++) {
      merge(son[x][i]);
      if (endp[x].size()<endp[son[x][i]].size()) swap(endp[x],endp[son[x][i]]);
      for (it=endp[son[x][i]].begin();it!=endp[son[x][i]].end();++it) {
        endp[x].insert(*it);
        it2=endp[x].lower_bound(*it);
        itq=itp=it2;
        if (itp!=endp[x].begin()) {
          --itp;
          pp[++cc]=(pir){*itp,*it,len[x]};
        }
        {
          itq++;
          if (itq!=endp[x].end()) pp[++cc]=(pir){*it,*itq,len[x]};
        }
        endp[x].erase(*it);
      }
      for (it=endp[son[x][i]].begin();it!=endp[son[x][i]].end();++it) endp[x].insert(*it);
    }
  }
} sam;

struct Fenwick{
  int a[N];
  void insert(int loc,int v) {
    loc=n-loc+1;
    for (ri i=loc;i<=n;i+=(i&(-i))) a[i]=max(a[i],v);
  }
  int find(int loc) {
    loc=n-loc+1;
    int ans=0;
    for (ri i=loc;i;i-=(i&(-i))) ans=max(ans,a[i]);
    return ans;
  }
} fg;

int main(){
  scanf("%d %d",&n,&q);
  sam.clear();
  scanf("%s",s+1);
  int l=strlen(s+1);
  for (ri i=1;i<=l;i++) sam.extend(s[i]-'0');
  for (ri i=1;i<=q;i++) {
    scanf("%d %d",&qu[i].l,&qu[i].r);
    qu[i].id=i;
  }
  sam.maketree();
  cc=0; sam.merge(1);
  sort(qu+1,qu+q+1);
  sort(pp+1,pp+cc+1);
  int p=1;
  for (ri i=1;i<=q;i++) {
    while (pp[p].r<=qu[i].r && p<=cc) fg.insert(pp[p].l,pp[p].v),p++;
    ans[qu[i].id]=fg.find(qu[i].l);
  }
  for (ri i=1;i<=q;i++) printf("%d
",ans[i]);
  return 0;
}
原文地址:https://www.cnblogs.com/shxnb666/p/11279340.html