GYM 101086 C.Everything(字典树)
2017-03-23 12:10
316 查看
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
类似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 555555 int 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 H.Another Square in the Floor(水~)
- 【贪心】【字典树】Gym - 101466A - Gaby And Addition
- GYM 101086 J.Smooth Developer(dfs)
- GYM 101086 K.Betrayed(树形DP+概率DP)
- GYM 101086 L.Chance(水~)
- Gym 101086 A, L ,G,H ,F 题解
- GYM 101086 M.ACPC Headquarters : AASTMT (Stairway to Heaven)(map)
- Gym 100935F A Poet Computer (字典树)
- GYM 100883 E.xortion(字典树)
- Gym 101086 M ACPC Headquarters : AASTMT (Stairway to Heaven)
- Gym 101086 A,F,G,H,L 五个水题
- GYM 101086 A.My Friend of Misery(水~)
- gym 100935B (字典树)
- GYM 101086 B.Brother Louie(dfs)
- [字典树 最小树形图] Codeforces Gym 100307 NEERC 13 D. Dictionary
- GYM 101086 D.Secure but True(水~)
- GYM 101086 F.Hey JUDgE(枚举)
- gym 100548题解(2014年西安现场赛(回文树,01字典树,容斥))
- GYM 101086 G.Paradise City(水~)
- CodeForces Gym 100971J 感觉题意有问题 BFS