bzoj3448[Usaco2014 Feb]Auto-complete*

bzoj3448[Usaco2014 Feb]Auto-complete

题意:

给个字符串集,询问字符串集中以字符串s为前缀的第k小字符串编号多少。字符串集总长度≤3000000,询问数≤1000,询问字符串长度≤1000。

题解:

先吐槽一下bzoj:自己加强了数据也不说一声,明明字符串集总长度不只1000000,不过我也不知道是不是3000000,反正2000000会RE。

一看到字符串集,以为是trie,结果又MLE又TLE,改左兄弟右儿子表示法又写炸。看题解trie求DFS序然后用主席树维护……天啊怎么银组题也这么劲QAQ。后来受神犇ccz受教,原来只要先给字符串集排序,然后二分找区间就行了,usaco题解也是这样写的。写完了结果re无数次,本机测usaco数据什么事也没有,最后一怒之下数组开到3000000,过了~注意因为只给出字符串集总长度不知道字符串个数,所以字符串要用一个链表维护。(然而正常人都是用STLstring不会RE不说代码还比我少一半,我太弱了QAQ)

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 3000010
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 using namespace std;
 7 
 8 inline int read(){
 9     char ch=getchar(); int f=1,x=0;
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
11     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
12     return f*x;
13 }
14 struct hd{int nx,id;}; hd hds[maxn];
15 struct nd{char ch; int nx;}; nd nds[maxn]; int ndss;
16 bool cmp(hd a,hd b){
17     int j=a.nx,k=b.nx;
18     while(j&&k){
19         if(nds[j].ch<nds[k].ch)return 1;
20         if(nds[j].ch>nds[k].ch)return 0;
21         j=nds[j].nx; k=nds[k].nx;
22     }
23     if(!j&&!k)return a.id<b.id;
24     if(!j)return 1;else return 0;
25 }
26 int w,n; char str[maxn];
27 int check(int x){
28     x=hds[x].nx; int len=strlen(str+1);
29     for(int i=1;i<=len;i++,x=nds[x].nx){
30         if(!x||str[i]>nds[x].ch)return 1;
31         if(str[i]<nds[x].ch)return -1;
32     }
33     return 0;
34 }
35 int main(){
36     w=read(); n=read();
37     inc(i,1,w){
38         char ch=getchar(); while(ch<'a'||ch>'z')ch=getchar();
39         hds[i]=(hd){++ndss,i};
40         while(ch>='a'&&ch<='z')
41             nds[ndss]=(nd){ch,ndss+1},ndss++,ch=getchar();
42         nds[--ndss].nx=0;
43     }
44     sort(hds+1,hds+1+w,cmp);
45     inc(i,1,n){
46         int k=read(); scanf("%s",str+1);
47         int q=-1,l=1,r=w;
48         while(l<=r){
49             int mid=(l+r)>>1; int c=check(mid);
50             if(c==0)q=mid,r=mid-1;
51             else if(c==-1)r=mid-1;else l=mid+1;
52         }
53         if(q==-1||q+k-1>w||check(q+k-1)!=0)printf("-1\n");
54         else printf("%d\n",hds[q+k-1].id);
55     }
56     return 0;
57 }

 

20160824

posted @ 2016-08-24 22:45  YuanZiming  阅读(361)  评论(0编辑  收藏  举报