神牛的養成計劃---可持久化trie
阿新 • • 發佈:2019-02-16
題目大意
給定n個由小寫字母組成的字串。現在有m個詢問,每個詢問指定兩個字串s1,s2.要求回答:在給定的n個字串中,有多少個字串s滿足:s1是s的字首且s2是s的字尾。強制線上!
資料範圍
限制
時間限制:1s
空間限制:256M (512M) (原題限制256M,這個太喪心病狂了!作為蒟蒻,我只會寫512M限制的!)
題解
對給定的n個字串建一棵字典樹.對於詢問,我們先在trie上匹配,假設最後停在了p節點,那麼所有滿足條件的字串s的末尾節點一定是在p的子樹中的。如果我們把原字串按照字典序排序(其實就是trie的dfs序),那麼滿足條件的s所對應的編號一定落在某個連續區間內。於是我們用可持久化trie維護字尾就好了。
第一次寫可持久化trie,感覺還算比較好寫。
看別人的題解,都是自定義cmp函式,然後sort一下。只有我蠢蠢地按dfs序排序。
程式碼
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 2000100
char s[MAXN],t[MAXN];
int _l[MAXN],_r[MAXN];
int n,m,tot=1 ;
int to[MAXN][26],rt[MAXN],nxt[MAXN][26],summ[MAXN],mn[MAXN],mx[MAXN],order[MAXN];
int C[MAXN];
vector<int>P[MAXN];
void ins(int id)
{
int x,p=1;
for(int i=0;t[i]!='\0';i++)
{
x=t[i]-'a';
if(!to[p][x])
{
to[p][x]=++tot;
}
p=to[p][x];
}
P[p].push_back(id);
return ;
}
int tim=0;
const int inf=0x3c3c3c3c;
void dfs(int p)
{
mn[p]=inf;
mx[p]=0;
for(int i=0;i<P[p].size();i++)
{
order[P[p][i]]=++tim;
mn[p]=min(mn[p],tim);
mx[p]=max(mx[p],tim);
}
for(int i=0;i<26;i++)
{
if(to[p][i])
{
dfs(to[p][i]);
mn[p]=min(mn[p],mn[to[p][i]]);
mx[p]=max(mx[p],mx[to[p][i]]);
}
}
return ;
}
bool cmp(int a,int b)
{
return order[a]<order[b];
}
void ins2(int& p,int f,int d,int pp)
{
p=++tot;
summ[p]=summ[f]+1;
memcpy(nxt[p],nxt[f],sizeof(nxt[f]));
if(d>pp)
{
ins2(nxt[p][s[d]-'a'],nxt[f][s[d]-'a'],d-1,pp);
}
return ;
}
int lstans=0;
int main()
{
scanf("%d",&n);
for(int i=1,tmp;i<=n;i++)
{
scanf("%s",t);
_l[i]=_r[i-1]+1;
tmp=strlen(t);
_r[i]=_l[i]+tmp-1;
for(int j=0;j<tmp;j++)
{
s[_l[i]+j]=t[j];
}
C[i]=i;
ins(i);
}
dfs(1);
sort(C+1,C+1+n,cmp);
tot=1;
for(int i=1,I;i<=n;i++)
{
I=C[i];
ins2(rt[i],rt[i-1],_r[I],_l[I]);
}
int L,R;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",t);
L=inf;
R=0;
int x=1;
for(int c,j=0;t[j]!='\0';j++)
{
c=t[j]-'a';
c=c+lstans;
c%=26;//這個傻逼錯誤,我調了半天才發現!!c-=c>=26?26:0;
x=to[x][c];
}
if(x)
{
L=mn[x];
R=mx[x];
}
scanf("%s",t);
if(L>R)
{
lstans=0;
}
else
{
int x=rt[L-1],y=rt[R],c,nn=strlen(t);
for(int j=nn-1;j>=0;j--)
{
c=t[j]-'a';
c=c+lstans;
c%=26;//c-=c>=26?26:0;
x=nxt[x][c];
y=nxt[y][c];
}
lstans=summ[y]-summ[x];
}
printf("%d\n",lstans);
}
return 0;
}