1. 程式人生 > >神牛的養成計劃---可持久化trie

神牛的養成計劃---可持久化trie

題目大意

給定n個由小寫字母組成的字串。現在有m個詢問,每個詢問指定兩個字串s1,s2.要求回答:在給定的n個字串中,有多少個字串s滿足:s1是s的字首且s2是s的字尾。強制線上!

資料範圍

nL12106ms1,s2L22106,n2000m100000.

限制

時間限制: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; }