题解:P7475 「C.E.L.U-02」简易输入法
题意
给定词典
,每次询问读入一个字符串 ,以及一个整数 对于这个字符串有以下几种情形: 设
且 为 的前缀的个数为 。 当
时,请输出按照以输出次数从大到小为第一关键字,以字典序为第二关键字排序后的第 个 ,并将其输出次数加 。 当
时,请输出按照以输出次数从大到小为第一关键字,以字典序为第二关键字排序后的最后一个 ,并将其输出次数加 。 当
时,输出 404Error
。
分析
前缀相关的统计操作,考虑使用 Trie。
带修改查询第
在每个 Trie 节点上维护一棵平衡树,维护所有包含该前缀的
因为
查询的时候在尾节点上询问即可。
时间复杂度
Code
因为不想重载运算符所以维护的是输出次数的相反数。
#include<bits/stdc++.h> #include<bits/extc++.h> using namespace std; using namespace __gnu_pbds; struct node { node* ch[26]; tree<pair<int, string>, null_type, less<pair<int, string>>, rb_tree_tag, tree_order_statistics_node_update> tr; node() {memset(ch, 0, sizeof ch);} }*rt=new node; unordered_map<string, int> mpt; void insert(string s) { node *x=rt; for(auto c:s) { x->tr.insert({0, s}); if(!x->ch[c-'a']) x->ch[c-'a']=new node; x=x->ch[c-'a']; } x->tr.insert({0, s}); mpt[s]=0; } void modify(string s) { node *x=rt; int v=mpt[s]; for(auto c:s) { x->tr.erase({v, s}); x->tr.insert({v-1, s}); x=x->ch[c-'a']; } x->tr.erase({v, s}); x->tr.insert({v-1, s}); mpt[s]--; } string query(string s, int v) { node *x=rt; for(auto c:s) { if(!x->ch[c-'a']) return "404Error"; x=x->ch[c-'a']; } string p=x->tr.find_by_order(min(v, (int)x->tr.size())-1)->second; modify(p); return p; } int main() { int n, t, x; string p; cin>>n; for(int i=1;i<=n;i++) cin>>p, insert(p); cin>>t; while(t--) cin>>p>>x, cout<<query(p, x)<<'\n'; }
本文作者:Jimmy-LEEE
本文链接:https://www.cnblogs.com/redacted-area/p/18379560
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步