題目大意:給定模板串,和一個長度爲的詢問序列,每個詢問操作爲把詢問串的到的子串在模板串中的出現次數,共個真正的詢問,每個會給定一個長度爲的串,問操作的詢問答案之和。
做法:對題目稍加觀察,和的數據範圍有明顯提示,可以確定根據與的關係進行數據分治,對於的,具有的特點是每個詢問的串長小,這樣就可以對每一個後綴直接插入進行詢問。而時,特點爲較小,可以直接把對應詢問序列裏面的詢問拆解,逐個詢問。而對於出現多少次,可以把模板串和詢問串放在一起建,每次找到區間最小值分治。這樣我們按照詢問長度從大到小的順序詢問,在詢問長度減小的過程中會不斷有分治的區間合併。採用分塊的方式來區間加單點求和。
時間複雜度:
感覺有很多更簡潔的做法,我寫了5k。還是太菜了,下次希望想一點簡便的做法。
代碼:
#include<iostream>
#include<cstring>
#include<cassert>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<time.h>
#include<bitset>
#include<cstdio>
#include<algorithm>
using namespace std;
#define REP(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,n) REP(i,1,n)
#define rep0(i,n) REP(i,0,n-1)
#define repG(i,x) for(int i=pos[x];~i;i=e[i].next)
#define ll long long
#define db double
const int N=3e5+7;
const int INF=1e9+7;
namespace seg{
const int T=320;
int tg[N],a[N];
void ins(int L,int R,int v){
if(L/T==R/T){
REP(i,L,R)a[i]+=v;
return;
}
while(L%T!=0)a[L++]+=v;
a[R]+=v;
while(R%T!=0)a[--R]+=v;
REP(i,L/T,R/T-1)tg[i]+=v;
}
int check(int x){return a[x]+tg[x/T];}
}
namespace SA{
int n,cnt;
int a[N],sa[N],ra[N],ns[N],nr[N],ls[N],ct[N],nw[N],mn[N*2],sm[N];
char s[N];
struct pir{int x,v;}p[N],h[N][22];
pir mer(pir a,pir b){return (a.v<b.v)?a:b;}
bool cmp(pir a,pir b){return a.v<b.v;}
struct tri{int x,l,r,v;}t[N*2];
bool cmp2(tri a,tri b){return a.x>b.x;}
pir check(int L,int R){
int k=mn[R-L+1];
return mer(h[L][k],h[R-(1<<k)+1][k]);
}
void solve(int l,int r){
if(l==r)return;
pir o=check(l,r-1);
t[++cnt]=(tri){o.v,l,o.x,sm[r]-sm[o.x]};
t[++cnt]=(tri){o.v,o.x+1,r,sm[o.x]-sm[l-1]};
if(!r)return;
solve(l,o.x);
solve(o.x+1,r);
}
void wk(){
rep(i,n)p[i]=(pir){i,a[i]};
sort(p+1,p+n+1,cmp);
int las=1;
rep(i,n){
if(p[i].v!=p[i-1].v)las=i;
ra[p[i].x]=las;
sa[i]=p[i].x;
}
for(int i=1;i<n;i<<=1){
rep(j,n)ct[j]=ls[j]=nw[j]=-1;
REP(j,n-i+1,n){
nw[ra[j]]++;
ns[ra[j]]=j;
nr[j]=ra[j];
}
rep(j,n){
if(sa[j]<=i)continue;
int p=sa[j]-i;
nw[ra[p]]++;
if(ra[sa[j]]!=ct[ra[p]]){
ct[ra[p]]=ra[sa[j]];
ls[ra[p]]=nw[ra[p]];
}
ns[ra[p]+nw[ra[p]]]=p;
nr[p]=ra[p]+ls[ra[p]];
}
rep(j,n)sa[j]=ns[j],ra[j]=nr[j];
}
int ans=0;
rep(i,n){
if(ra[i]==n){
ans=0;
continue;
}
if(ans)ans--;
int p=sa[ra[i]+1];
while(a[p+ans]==a[i+ans]&&i+ans<=n&&p+ans<=n)ans++;
h[ra[i]][0]=(pir){ra[i],ans};
}
for(int i=1;(1<<i)<n;i++){
rep(j,n-(1<<i))h[j][i]=mer(h[j][i-1],h[j+(1<<(i-1))][i-1]);
REP(j,(1<<i)+1,(1<<(i+1)))mn[j]=i;
}
}
void init(int *b,int nn,int gg){
n=nn;
cnt=0;
rep(i,n)a[i]=b[i];
wk();
rep(i,gg)sm[ra[i]]++;
rep(i,n)sm[i]+=sm[i-1];
solve(1,n);
sort(t+1,t+cnt+1,cmp2);
}
}
int n,m,Q,K;
namespace D1{
int L[N],R[N],wa[N],bg[N],u[N],v[N],p[N];
ll Ans[N];
int cnt,tot;
char s[N];
vector<int>g[N];
bool cmp(int x,int y){return (R[x]-L[x])>(R[y]-L[y]);}
void solve(){
scanf("%s",s+1);
cnt=tot=0;
rep(i,n)wa[++cnt]=s[i]-'a';
rep(i,m)scanf("%d%d",&L[i],&R[i]);
rep(i,m)L[i]++,R[i]++;
rep(i,Q){
scanf("%s%d%d",s+1,&u[i],&v[i]);
u[i]++;
v[i]++;
wa[++cnt]=-1;
bg[i]=cnt;
rep(j,K)wa[++cnt]=s[j]-'a';
REP(j,u[i],v[i])g[j].push_back(i);
}
SA::init(wa,cnt,n);
rep(i,m)p[i]=i;
sort(p+1,p+m+1,cmp);
int nw=1;
rep(i,m){
while(nw<=SA::cnt&&SA::t[nw].x>=R[p[i]]-L[p[i]]+1){
seg::ins(SA::t[nw].l,SA::t[nw].r,SA::t[nw].v);
nw++;
}
for(int j=0;j<g[p[i]].size();j++){
int d=g[p[i]][j];
Ans[d]+=(ll)seg::check(SA::ra[bg[d]+L[p[i]]]);
}
}
rep(i,Q)printf("%lld\n",Ans[i]);
}
}
namespace D2{
const int T=320;
int L[N],R[N],sz[N],sm[T][T];
char s[N],sv[N];
vector<int>sg[N];
struct sam{
int p,l;
int to[26];
}t[N*2];
int cnt,ls,tot;
int ins(int x){
t[++cnt].l=t[ls].l+1;
int i=ls;
ls=cnt;
for(;i;i=t[i].p){
if(t[i].to[x])break;
t[i].to[x]=cnt;
}
if(!i){t[cnt].p=1; return ls;}
int q=t[i].to[x];
if(t[q].l==t[i].l+1){t[cnt].p=q; return ls;}
t[++cnt]=t[q];
t[cnt].l=t[i].l+1;
t[ls].p=cnt;
t[q].p=cnt;
for(;i;i=t[i].p){
if(t[i].to[x]!=q)break;
t[i].to[x]=cnt;
}
return ls;
}
vector<int>E[N];
void dfs(int x){
for(int j=0;j<E[x].size();j++){
dfs(E[x][j]);
sz[x]+=sz[E[x][j]];
}
}
struct pir{int x,v,d;}tt[N];
bool cmp(pir u,pir v){return u.x<v.x;}
void solve(){
scanf("%s",s+1);
cnt=ls=1;
tot=0;
rep(i,n)sz[ins(s[i]-'a')]++;
REP(i,2,cnt)E[t[i].p].push_back(i);
dfs(1);
rep(i,m)scanf("%d%d",&L[i],&R[i]);
rep(i,m)L[i]++,R[i]++;
rep(i,Q){
scanf("%s",s+1);
rep(j,K){
sv[(i-1)*K+j]=s[j];
rep(k,K+1)sg[(i-1)*K+j].push_back(0);
}
int x,y; scanf("%d%d",&x,&y);
x++; y++;
if(x>1)tt[++tot]=(pir){x-1,-1,i};
tt[++tot]=(pir){y,1,i};
}
sort(tt+1,tt+tot+1,cmp);
int nw=1;
rep(i,m){
sm[L[i]][R[i]]++;
while(nw<=tot&&tt[nw].x==i){
rep(j,K)REP(k,j,K)sg[(tt[nw].d-1)*K+j][k]+=tt[nw].v*sm[j][k];
nw++;
}
}
rep(i,Q){
ll ans=0;
int bb=(i-1)*K;
rep(j,K){
int nw=1;
REP(k,j,K){
if(!t[nw].to[sv[bb+k]-'a'])break;
nw=t[nw].to[sv[bb+k]-'a'];
ans+=(ll)sg[bb+j][k]*sz[nw];
}
}
printf("%lld\n",ans);
}
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&Q,&K);
if(K*K>=m)D1::solve();
else D2::solve();
return 0;
}
由於疫情的原因,閒着也是閒着,就寫了這篇博客