題目大意
給定$n$個字串$s$,$m$次詢問,每次詢問給定兩個字串$s_1,s_2$,求$n$個字串中有多少個串滿足$s_1$是其字首且$s_2$是其字尾。
$n\leq 2000,m\leq 10^5 \sum |s|,\sum (|s_1|+|s_2|) \leq 2\times 10^6$
題解考慮正反建$trie$樹,原題就變為了在兩棵子樹中均出現的點有多少個。
你當然可以用主席樹加二維數點解決,其實也可以將每乙個串按照正向$trie$樹$dfs$序排序,然後再反向建可持久化$trie$,每次詢問就先找到正向$dfs$序要求的區間,接著在可持久化$trie$的兩個對應的根中沿著$s_2$的反串得出答案。
複雜度為$o(n\log n+\sum |s|+\sum (|s_1|+|s_2|)+m\log n)$。
所以其實$n$甚至可以出成$10^5$級。
#include#include#include#include#include#define ll long long#define m 2220000
#define n 2010
using namespace std;
namespace io
void putchar(char c)
void write(int x) if(x<0) x=-x,putchar('-');
while(x) ss[++top]=x%10,x/=10;
while(top) putchar(ss[top]+'0'),--top;
} int read()
}using namespace io;
char ch[m],*s[n],s1[m],s2[m]; int n,m,p[m][26],tg[n],len[n];
int sz[m],dfn[m],node[n],tot,rt,rt[n];
int cnt,t[m][26],od[n],sum[m];
int ins(int &x,char *k,int rem)
void dfs(int x)
bool cmp(int x,int y) return res;
}int main() dfs(rt),cnt=0,sort(od+1,od+n+1,cmp);
for(int i=1;i<=n;i++) ist(rt[i],rt[i-1],s[od[i]]+len[od[i]]-1,len[od[i]]);
for(int t=read(),ans=0,len1,len2,l,r;t;t--,write(ans),putchar('\n'))
l=fd(l-1),r=fd(r),ans=qry(rt[r],rt[l],s2+len2-1,len2);
}flush();return 0;
}
bzoj4212 神牛的養成計畫
portal bzoj4212 資料範圍 n 2000,m 100000 n 個字串總長度以及詢問字串總長度均 2000000 怎麼感覺自己好像沒有學過trie一樣是因為太久沒有寫所以根本沒有往那個方向想嗎 最暴力的做法的話。想法很簡單 先確定哪些字串滿足 s 1 是字首,再看其中滿足 s 2 是字...
P2006 趙神牛的遊戲
題目描述 在 dnf 中,趙神牛有乙個締造者,他一共有 kk 點法力值,一共有 mm 個技能,每個技能耗費的法力值為 a ia i,可以造成的傷害為 b ib i,而 boss 的體力值為 nn,請你求出它放哪個技能,才可以打死 boss。當然,趙神牛技術很菜,他一局只放乙個技能,不過每個技能都可以...
bzoj1635 最高的牛
初始如果沒有限制,很顯然每一頭牛高度都是h 當只有乙個限制,讓h a 到h b 的高度都減1即可 容易發現兩個限制不會相交 否則必然矛盾 只會包含或相離,因此沒有影響,直接差分 線段樹即可 注意 1.不保證a 1 include2 using namespace std 3struct jia 10...