LOJ # 6031. "Yali training 2017 Day1" string

\ (SAM \) + Category talk

First to build a \ (SAM \) and then calculated the \ (| {\ rm endpos} (p) | \)

$ \ Sum w = kq \ leq 10 ^ 5 $, then to \ (K \) size classification discussed.

\ (K \ GEQ \ n-sqrt \) , \ (Q \ Leq \ n-sqrt \) , directly in the \ (the SAM \) matching \ (W \) , each position is determined in \ (the SAM \) points on . For each interrogation, multiplication jump upwardly against the upper most and \ ({\ rm len} ( p) \ geq qr-ql + 1 \) point, plus answer \ (| {\ rm endpos} (p) | \) .

In this case Q \ leqslant \ sqrt {} n- Qn- , we direct the SAM S A M violence matching W W , find all W W prefix corresponding to a node, then enumeration interrogation, multiplication jump w [l_i .. .r_i] W [ L I ... R & lt I ] of this node, together with the answer of the node endpos E * n- D P O * S ** size can be set.

\ (K <\ n-sqrt \) , \ (Q> \ n-sqrt \) , consider the case \ (qK ^ 2 \) algorithm, we can start a tub \ (v [ql] [qr ] \) Record All inquiries, and enumerate \ (W \) all prefixes match, it was separated in two \ ([a, b] \ ) frequency interval this query appears, by the added length of the matching answers.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
  do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=200010,B=17,D=350;
int n,m,Q,K,tot=1,lst=1;
int LL[N],RR[N],f[N][B+1];
int fa[N],c[N][26],len[N],d[N],sz[N],mem[N];
char s[N];
inline void add(int ch) {
  R p=lst,np=lst=++tot;
  len[np]=len[p]+1,++sz[tot];
  while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
  if(!p) return fa[np]=1,void();
  R q=c[p][ch];
  if(len[q]==len[p]+1) return fa[np]=q,void();
  else {
    R nq=++tot;
    memcpy(c[nq],c[q],26<<2);
    fa[nq]=fa[q],len[nq]=len[p]+1;
    fa[np]=fa[q]=nq;
    while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p]; 
  }
}
int mp[N],ml[N];
inline void solve1() {
  register ll ans;
  for(R i=1;i<=m;++i) LL[i]=g()+1,RR[i]=g()+1;
  while(Q--) {
    scanf("%s",s+1);
    R ql=g()+1,qr=g()+1;
    R p=1,l=0;
    for(R i=1;i<=K;++i) {
      R ch=s[i]-'a';
      while(p&&!c[p][ch]) p=fa[p],l=len[p];
      if(!p) {p=1,l=0,mp[i]=0; continue;}
      p=c[p][ch],++l,mp[i]=p,ml[i]=l;
    } ans=0;
    for(R i=ql,p,l,lim;i<=qr;++i) {
      p=mp[RR[i]],l=ml[RR[i]],lim=RR[i]-LL[i]+1;
      if(!p||l<lim) continue;
      for(R t=B;~t;--t) if(f[p][t]&&len[f[p][t]]>=lim)
        p=f[p][t];
      ans+=sz[p];
    } printf("%lld\n",ans);
  }
}
vector<int> q[D][D];
inline void solve2() {
  register ll ans=0;
  for(R i=1,l,r;i<=m;++i) 
    l=g()+1,r=g()+1,q[l][r].push_back(i);
  while(Q--) {
    ans=0;
    scanf("%s",s+1);
    R ql=g()+1,qr=g()+1;
    for(R i=1;i<=K;++i) for(R j=i,p=1;j<=K;++j) {
      p=c[p][s[j]-'a']; if(!p) break;
      ans+=1ll*(upper_bound(q[i][j].begin(),q[i][j].end(),qr)-
                lower_bound(q[i][j].begin(),q[i][j].end(),ql))*sz[p];
    } printf("%lld\n",ans);
  }  
}
inline void main() {
  n=g(),m=g(),Q=g(),K=g();
  scanf("%s",s+1);
  for(R i=1;i<=n;++i) add(s[i]-'a');
  for(R i=1;i<=tot;++i) ++d[len[i]];
  for(R i=1;i<=n;++i) d[i]+=d[i-1];
  for(R i=1;i<=tot;++i) mem[d[len[i]]--]=i;
  for(R i=tot;i;--i) sz[fa[mem[i]]]+=sz[mem[i]];
  for(R i=1;i<=tot;++i) f[i][0]=fa[i];
  for(R t=1;t<=B;++t) for(R i=1;i<=tot;++i)
    f[i][t]=f[f[i][t-1]][t-1];
  if(K>=sqrt(n)) solve1();
  else solve2();
}
} signed main() {Luitaryi::main(); return 0;}

2020.01.10

Guess you like

Origin www.cnblogs.com/Jackpei/p/12177585.html