您的位置:首页 > 产品设计

[BZOJ3439]Kpm的MC密码

2018-03-14 08:59 309 查看

题目大意:
  给定$n(n\leq10^5)$个字符串$s_{1\sim n}$,$n$次询问,每次询问所有满足$s_i$是$t$的后缀的$t$中,编号第$k_i$小的$t$的编号。

思路:
  倒着建字典树,根据DFS序建立主席树,维护每个区间内编号出现次数。

#include<list>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=100001,logN=18,S=26;
int n;
class FotileTree {
private:
struct Node {
int val,left,right,vis;
};
Node node[N*logN];
int sz,new_node(const int &p,const int &id) {
node[++sz]=node

; node[sz].vis=id; return sz; } public: int root ; void modify(int &p,const int &b,const int &e,const int &x,const int &y,const int &id) { if(node[p].vis!=id) p=new_node(p,id); node[p].val+=y; if(b==e) return; const int mid=(b+e)>>1; if(x<=mid) modify(node[p].left,b,mid,x,y,id); if(x>mid) modify(node[p].right,mid+1,e,x,y,id); } int query(const int &p,const int &q,const int &b,const int &e,const int &k) { if(node[q].val-node[p].val<k) return -1; if(b==e) return b; const int mid=(b+e)>>1; if(node[node[q].left].val-node[node[p].left].val>=k) return query(node[p].left,node[q].left,b,mid,k); return query(node[p].right,node[q].right,mid+1,e,k-(node[node[q].left].val-node[node[p].left].val)); } }; FotileTree t; class Trie { private: int pos ,ch [S],par ,dfn ,size ,cnt; std::list<int> val ; int sz,new_node(const int &p) { par[++sz]=p; return sz; } int idx(const char &c) const { return c-'a'; } void push_up(const int &p) { size[p]=1; for(register int i=0;i<S;i++) size[p]+=size[ch[p][i]]; } public: void insert(const char s[],const int &id) { int u=0; for(register int i=0;s[i];i++) { u=ch[u][idx(s[i])]=ch[u][idx(s[i])]?:new_node(u); } val[pos[id]=u].push_back(id); for(;u;u=par[u]) push_up(u); } void dfs(const int &x) { dfn[x]=cnt++; if(dfn[x]) t.root[dfn[x]]=t.root[dfn[x]-1]; for(register std::list<int>::iterator i=val[x].begin();i!=val[x].end();i++) { t.modify(t.root[dfn[x]],1,n,*i,1,dfn[x]); } for(int i=0;i<S;i++) { if(ch[x][i]) dfs(ch[x][i]); } } int query(const int &id,const int &k) { return t.query(t.root[dfn[pos[id]]-1],t.root[dfn[pos[id]]+size[pos[id]]-1],1,n,k); } }; Trie trie; char s ; int main() { n=getint(); for(register int i=1;i<=n;i++) { scanf("%s",s); std::reverse(&s[0],&s[strlen(s)]); trie.insert(s,i); } trie.dfs(0); for(register int i=1;i<=n;i++) { printf("%d\n",trie.query(i,getint())); } return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: