GYM 101086 C.Everything(字典树)
来源:互联网 发布:知乎施工排水 编辑:程序博客网 时间:2024/04/28 06:18
Description
类似everything的搜索功能,所有字符串按字典序升序排,每次键入一个前缀光标就会移动到以该前缀为前缀的所有字符串中字典序最小的那个上面,每次键入一个字符串算一次操作,按一下上下键也算一次操作,给出n个串,问在everything中找到该串至少需要几步操作
Input
第一行一整数T表示用例组数,每组用例首先输入字符串数量n,之后n个全由小写字母组成的字符串,每个串串长不超过1e5,总串长不超过5e5(1<=T<=100,1<=n<=1e5)
Output
对于每组用例,输出n个整数,第i个数表示查询到第i个字符串至少几步操作
Sample Input
2
5
scpc
acm
syria
acpc
accepted
5
feglathegreat
candidatesamerraed
masterhossamyousef
candidateabdullahbahosain
masterhassanalhamsh
Sample Output
2 2 2 3 1
2 2 2 1 2
Solution
把所有串插入字典树中,对于每个串s的查询,设s串长为m,在字典树上dfs,不断增加要键入的前缀长度,对于每个前缀的最后一个字符x,有两种情况,一种是就键入x然后往下找,另一种是键入x+1然后往上找,所以在dfs的过程中要维护当前缀长度为i时字典序在s[1,i]前面的串数pre[i]和后面的串数next[i],已经键入长度为i的前缀时,往下找要找pre[m]-pre[i],故总操作数是i+pre[m]-pre[i],或者再键入s[i+1]+1然后往上找,往上要找next[m]-next[i],此时总操作数是i+1+next[m]-next[i],每层都拿这两个值更新一个最小值即可
Code
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define maxn 555555int T,n,no,ch[maxn][26],id[maxn],cnt[maxn],sum[maxn],ans,Pre,Next;char c[maxn],s[maxn];void init(){ memset(ch[0],-1,sizeof(ch[0])); cnt[0]=0,id[0]=-1,no=0;}void insert(char *s,int _id){ int u=0; cnt[0]++; for(int i=0;s[i];i++) { int c=s[i]-'a'; if(ch[u][c]==-1) { ch[u][c]=++no; memset(ch[no],-1,sizeof(ch[no])); cnt[no]=0,id[no]=-1; } u=ch[u][c]; cnt[u]++; } id[u]=_id;}void dfs(int l,int r,int u,int pre,int next,int deep){ if(l==r) { ans=min(ans,deep),Pre=pre,Next=next+cnt[u]-1; return ; } int c=s[l]-'a',tpre=pre,tnext=next; for(int i=0;i<c;i++) if(ch[u][i]!=-1)tpre+=cnt[ch[u][i]]; if(id[u]!=-1)tpre++; for(int i=c+1;i<26;i++) if(ch[u][i]!=-1)tnext+=cnt[ch[u][i]]; dfs(l+1,r,ch[u][c],tpre,tnext,deep+1); ans=min(ans,deep+Pre-pre),ans=min(ans,deep+1+Next-next);}void Solve(int l,int r){ ans=INF,Pre=0,Next=0; dfs(l,r,0,0,0,1);}int main(){ scanf("%d",&T); while(T--) { init(); scanf("%d",&n); sum[0]=0; for(int i=1;i<=n;i++) { scanf("%s",c); int len=strlen(c); insert(c,i); sum[i]=sum[i-1]+len; for(int j=sum[i-1];j<sum[i];j++)s[j]=c[j-sum[i-1]]; } for(int i=1;i<=n;i++) { Solve(sum[i-1],sum[i]); printf("%d%c",ans,i==n?'\n':' '); } } return 0;}
- GYM 101086 C.Everything(字典树)
- GYM 100883 E.xortion(字典树)
- gym 100935B (字典树)
- gym 100548题解(2014年西安现场赛(回文树,01字典树,容斥))
- Gym 100935F A Poet Computer (字典树)
- CF Gym 字符串字典序
- Gym 100917D dir -C(RMQ)
- GYM 100090 C.Graph Restoration(Floyd)
- GYM 100488 C.Lost Temple(数论)
- GYM 100712 C.Street Lamps(贪心)
- GYM 101102 C.Bored Judge(map)
- GYM 100971 C.Triangles(水~)
- GYM 101061 C.Ramzi(SPFA)
- Codeforces Gym 101164 C. Castle (KMP)
- HDOJ 5687 Problem C (字典树)
- HDU 5687 Problem C(字典树)
- Everything原理(部分)
- CodeForces Gym 100114C
- win7下获取局域网内其他win或ubuntu系统电脑的MAC地址
- C语言中的值传递
- eth0 找不到
- 欢迎使用CSDN-markdown编辑器
- VB中WinSock控件的属性、方法、事件及应用
- GYM 101086 C.Everything(字典树)
- “玲珑杯”ACM比赛 Round #9 题解 (待续)
- jQuery插件开发中$.extend和$.fn.extend辨析
- 安装新旧版本的arm-linux-gcc交叉工具链(基于JZ2440)
- [递归]CODEVS-3145 汉诺塔游戏
- linux 一些命令
- 数据库三大范式
- **POJ 1008 Maya Calendar解题报告
- 关于Android图表开源库HelloChart的坐标属性设置