0316 校赛训练赛3 解题报告

A:

 

题目:

帽子
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 27(6 users) Total Accepted: 9(5 users) Rating:  Special Judge: No
Description
由字典里其他两个单词组成的单词为帽子单词,你要找到字典里所有的帽子单词。
Input

 

只有一组输入数据

输入包含若干个小写单词,每行一个单词并且按照字典序排序。最多不超过50000个单词。每个单词长度不超过15.

 

Output
你需要按照字典序输出字典中的所有帽子单词。
Sample Input
cat
catdog
dog
Sample Output
catdog
Source
HCPC2014校赛训练赛 3
Author
曹振海

这个题可以用map水过,省时的方法还是字典树

map代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 #include<map>
 5 using namespace std;
 6 
 7 map<string,int>mp;
 8 
 9 int main()
10 {
11     int k=0;
12     string str[50005];
13     //freopen("aa.txt","r",stdin);
14     while(cin>>str[k])
15     {
16         mp[str[k]]=1;
17         k++;
18     }
19     for(int i=0;i<k;i++)
20     {
21         int len=str[i].length();
22         for(int j=1;j<len;j++)
23         {
24             string s1=str[i].substr(0,j);
25             string s2=str[i].substr(j,len);
26             if(mp[s1]==1&&mp[s2]==1){
27             cout<<str[i]<<endl;
28             break;
29             }
30         }
31     }
32     return 0;
33 }
View Code

字典树数组模拟带代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 using namespace std;
 5 
 6 const int maxn=1000005;
 7 
 8 int tire[maxn][26];
 9 int flag[maxn];
10 int tot;
11 
12 void Insert(char *s,int rt)
13 {
14     int len=strlen(s);
15     for(int i=0;i<len;i++)
16     {
17         int x=s[i]-'a';
18         if(tire[rt][x]==0)
19         tire[rt][x]=tot++;
20         rt=tire[rt][x];
21     }
22     flag[rt]=1;
23 }
24 
25 bool Find2(char *s,int rt,int i)
26 {
27     int len=strlen(s);
28     for(int j=i;j<len;j++)
29     {
30         int x=s[j]-'a';
31         if(tire[rt][x]==0)
32         return false;
33         rt=tire[rt][x];
34     }
35     return flag[rt];
36 }
37 
38 bool Find(char *s,int rt)
39 {
40 
41     int len=strlen(s);
42     for(int i=0;i<len;i++)
43     {
44         int x=s[i]-'a';
45         if(tire[rt][x]==0)
46         return false;
47         if(flag[rt]&&Find2(s,0,i))
48         return true;
49         rt=tire[rt][x];
50     }
51     return false;
52 }
53 
54 int main()
55 {
56     int k=0;
57     tot=1;
58     char str[50005][20];
59     //freopen("aa.txt","r",stdin);
60     while(scanf("%s",str[k])!=EOF)
61     {
62         Insert(str[k],0);
63         k++;
64     }
65     for(int i=0;i<k;i++)
66     {
67         if(Find(str[i],0))
68         printf("%s\n",str[i]);
69     }
70     return 0;
71 }
View Code

字典树指针代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 using namespace std;
 5 
 6 struct tire
 7 {
 8     tire *next[26];
 9     bool flag;
10     tire()
11     {
12         for(int i=0;i<26;i++)
13         {
14             next[i]=NULL;
15             flag=false;
16         }
17     }
18 }root;
19 
20 void Insert(char *s)
21 {
22     tire *rt=&root;
23     for(int i=0;s[i];i++)
24     {
25         int x=s[i]-'a';
26         if(rt->next[x]==NULL)
27         {
28             rt->next[x]=new tire;
29         }
30         rt=rt->next[x];
31     }
32     rt->flag=true;
33 }
34 
35 bool Find2(char *s,int i)
36 {
37     tire *rt=&root;
38     for(int j=i;s[j];j++)
39     {
40         int x=s[j]-'a';
41         if(rt->next[x]==NULL)
42         return false;
43 
44         rt=rt->next[x];
45     }
46     return rt->flag;
47 }
48 
49 bool Find(char *s)
50 {
51     tire *rt=&root;
52     for(int i=0;s[i];i++)
53     {
54         int x=s[i]-'a';
55         if(rt->next[x]==NULL)
56         return false;
57 
58         if(rt->flag&&Find2(s,i))
59         return true;
60 
61         rt=rt->next[x];
62     }
63     return false;
64 }
65 
66 int main()
67 {
68     int k=0;
69     char str[50005][20];
70     //freopen("aa.txt","r",stdin);
71     while(scanf("%s",str[k])!=EOF)
72     {
73         Insert(str[k]);
74         k++;
75     }
76     for(int i=0;i<k;i++)
77     {
78         if(Find(str[i]))
79         printf("%s\n",str[i]);
80     }
81     return 0;
82 }
View Code

 

 

B:

 

背单词
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 47(25 users) Total Accepted: 29(24 users) Rating:  Special Judge: No
Description

大四了,Leyni感觉好惆怅,因为找不到工作,所以最后决定考研了,可是Leyni的英语好差,没办法,先从最基本的背单词开始吧。那么多单词怎么才好背呢,话说考研界盛传利用前缀背单词,貌似好神奇的样子。因为英语单词很多,Leyni想要知道以一个特定字符串做前缀的单词有多少,于是他来找你帮忙了。

Input
输入首先包含若干行小写单词,表示字典里的单词,以END结束,然后是若干个询问字符串,表示单词的前缀。输入到文件结束。最多不超过50000个单词。每个单词长度不超过15。
Output
对于每一个询问字符串,每行输出一个整数,表示单词表里有多少单词以此字符串作为前缀。
Sample Input
a
ab
aba
abcaa
END
aba
a
ab
abcd
Sample Output
1
4
3
0
Source
HCPC2014校赛训练赛 3
Author
曹振海

这个题同样可以用字典树和map做:

map代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 #include<map>
 5 using namespace std;
 6 
 7 map<string,int>mp;
 8 
 9 int main()
10 {
11     string s;
12     //freopen("aa.txt","r",stdin);
13     while(cin>>s)
14     {
15         if(s=="END")
16         break;
17         int len=s.length();
18         for(int i=0;i<=len;i++)
19         {
20             string s1=s.substr(0,i);
21             mp[s1]++;
22         }
23     }
24     while(cin>>s)
25     {
26         if(s=="END")
27         break;
28         cout<<mp[s]<<endl;
29     }
30     return 0;
31 }
View Code

字典树数组模拟:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 #include<map>
 5 using namespace std;
 6 
 7 const int maxn=1000005;
 8 
 9 int tire[maxn][26];
10 int num[maxn];
11 int tot;
12 
13 void Insert(char *s,int rt)
14 {
15     int len=strlen(s);
16     for(int i=0;i<len;i++)
17     {
18         int x=s[i]-'a';
19         if(tire[rt][x]==0)
20         tire[rt][x]=tot++;
21         rt=tire[rt][x];
22         num[rt]++;
23     }
24 }
25 
26 int Find(char *s,int rt)
27 {
28     int len=strlen(s);
29     for(int j=0;j<len;j++)
30     {
31         int x=s[j]-'a';
32         if(tire[rt][x]==0)
33         return 0;
34         rt=tire[rt][x];
35     }
36     return num[rt];
37 }
38 
39 int main()
40 {
41     char s[maxn];
42     tot=1;
43     //freopen("aa.txt","r",stdin);
44     while(scanf("%s",s))
45     {
46         if(strcmp(s,"END")==0)
47         break;
48         Insert(s,0);
49     }
50     while(scanf("%s",s)!=EOF)
51     {
52         printf("%d\n",Find(s,0));
53     }
54     return 0;
55 }
View Code

字典树指针:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 using namespace std;
 5 
 6 const int maxn=10005;
 7 
 8 struct tire
 9 {
10     tire *next[26];
11     int num;
12     tire()
13     {
14         for(int i=0;i<26;i++)
15         {
16             next[i]=NULL;
17             num=0;
18         }
19     }
20 }root;
21 
22 void Insert(char *s)
23 {
24     tire *rt=&root;
25     for(int i=0;s[i];i++)
26     {
27         int x=s[i]-'a';
28         if(rt->next[x]==NULL)
29         {
30             rt->next[x]=new tire;
31         }
32         rt=rt->next[x];
33         rt->num++;
34     }
35 }
36 
37 int Find(char *s)
38 {
39     tire *rt=&root;
40     for(int j=0;s[j];j++)
41     {
42         int x=s[j]-'a';
43         if(rt->next[x]==NULL)
44         return 0;
45         rt=rt->next[x];
46     }
47     return rt->num;
48 }
49 
50 int main()
51 {
52     char s[maxn];
53     //freopen("aa.txt","r",stdin);
54     while(scanf("%s",s))
55     {
56         if(strcmp(s,"END")==0)
57         break;
58         Insert(s);
59     }
60     while(scanf("%s",s)!=EOF)
61     {
62         printf("%d\n",Find(s));
63     }
64     return 0;
65 }
View Code

 

 

C:

 

搬果子
Time Limit: 2000 MS Memory Limit: 32768 K
Total Submit: 22(17 users) Total Accepted: 15(15 users) Rating:  Special Judge: No
Description
    果园里面有n堆果子,每堆果子有xi个,每个果子的重量为1,小明每次把i,j两堆果子移成一堆,需要花费的体力为xi+xj。最后移成一堆,求最小花费体力值。
其中1<=n<=10000,1<=m<=10000。均为正整数。
Input

    每组数据第一行输入一个正整数n,表示有n堆果子。

    接下来一行有n个正整数,表示每堆果子的重量。

    输入以EOF结尾。

Output
    每组数据单独一行,输出所花费的最小体力值。
Sample Input

3

1 2 9

5

1 3 9 18 30

Sample Output

15

109

Hint
 
Source
HCPC2014校赛训练赛 3
Author
BH

这个题可以用堆或者优先队列来写

优先队列模板:额……慢的要死

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<queue>
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     int n,num,ans;
10     //freopen("aa.txt","r",stdin);
11     while(scanf("%d",&n)!=EOF)
12     {
13         ans=0;
14         priority_queue<int,vector<int>,greater<int> >q;
15         while(n--)
16         {
17             scanf("%d",&num);
18             q.push(num);
19         }
20         while(q.size()>1)
21         {
22             int a1=q.top();
23             q.pop();
24             int a2=q.top();
25             q.pop();
26             ans+=(a1+a2);
27             q.push(a1+a2);
28         }
29         printf("%d\n",ans);
30     }
31     return 0;
32 }
View Code

堆(有点懒了,直接用的stl==)

 1 #include<iostream>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<stdio.h>
 5 #include<vector>
 6 using namespace std;
 7 
 8 const int maxn=10005;
 9 int a[maxn];
10 
11 bool cmp(int x,int y)
12 {
13     return x>y;
14 }
15 
16 int main()
17 {
18     int n;
19     //freopen("aa.txt","r",stdin);
20     while(scanf("%d",&n)!=EOF)
21     {
22         int ans=0;
23         for(int i=0;i<n;i++)
24         scanf("%d",&a[i]);
25         make_heap(a,a+n,cmp);
26         while(n>1){
27             pop_heap(a,a+n,cmp);
28             pop_heap(a,a+n-1,cmp);
29             a[n-2]+=a[n-1];
30             ans+=a[n-2];
31             n--;
32             push_heap(a,a+n,cmp);
33         }
34         printf("%d\n",ans);
35     }
36     return 0;
37 }
View Code

 

 

D:

截取方案数
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 29(14 users) Total Accepted: 18(14 users) Rating:  Special Judge: No
Description

给定一个模式串T,主串S,问:从S中截取T有多少种方案?

Input

有多组测试数据,对于每组测试数据,第一行是模式串T,第二行是主串S,数据中仅包含大小写字母和数字,模式串T长度不超过10^4, 主串S长度不超过10^5。

注意:数据是随机的。

Output

对于每组测试数据,输出一行,为截取方案数。

Sample Input
abc
abcdaabcab
abcd
abcdaabcab
aba
abababa
Sample Output
2
1
3

kmp模板题:

代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<stdio.h>
 5 #include<vector>
 6 using namespace std;
 7 
 8 const int maxn=100005;
 9 char s1[maxn],s2[maxn];
10 int next[maxn];
11 int len1,len2;
12 
13 void get_next()
14 {
15     int i,j;
16     next[1]=0;
17     for (i=0,j=2;j<=len2;j++)
18     {
19         while(i>0&&s2[i+1]!=s2[j])
20         i=next[i];
21         if(s2[i+1]==s2[j])
22         i++;
23         next[j]=i;
24     }
25 }
26 
27 int kmp()
28 {
29     int i,j,res=0;
30     for(i=1,j=0;i<=len2;i++)
31     {
32         while(j>0&&s1[j+1]!=s2[i])
33         j=next[j];
34         if(s1[j+1]==s2[i])
35         j++;
36         if(j==len1)
37         {
38             res++;
39             j=next[j];
40         }
41     }
42     return res;
43 }
44 
45 int main()
46 {
47     //freopen("aa.txt","r",stdin);
48     while(gets(s1+1))
49     {
50         gets(s2+1);
51         len1=strlen(s1+1);
52         len2=strlen(s2+1);
53         get_next();
54         printf("%d\n",kmp());
55     }
56     return 0;
57 }
View Code

 

E:

消息队列
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 35(14 users) Total Accepted: 12(11 users) Rating:  Special Judge: No
Description
Windows操作系统是基于消息的,也就是说任何的事件,包括鼠标移动和点击,键盘的输入,都会被放入操作系统的消息队列中,而消息本身带有一定的参数和优先级。Windows会优先处理优先级较高的消息,当两个消息优先级相同时,按照先来先服务的原则进行处理,你的任务就是模拟这种机制。
Input
输入首先分为两种,GET表示从消息队列中取出一个消息。PUT表示把一个消息放入消息队列,每一个消息包含三个部分:内容,参数和优先级(数字越小优先级越高)。输入亦按照此顺序进行。消息的内容长度不会超过15。最多不超过60000个操作。
Output
对于每一个GET操作,若队列为空,输出EMPTY QUEUE!否则输出按照规则得到的第一个消息的内容和参数。
Sample Input

GET

PUT msgone 11 6

PUT msgtwo 8 4

GET

GET

GET

Sample Output

EMPTY QUEUE!

msgtwo 8

msgone 11

EMPTY QUEUE!

Source
HCPC2014校赛训练赛 3
Author
曹振海

基于优先队列的基本操作

 

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 struct que{
 9     char str[20];
10     int youxian,canshu,shijian;
11 };
12 struct cmp{
13      bool operator()(const que &a,const que &b) {
14                      if(a.youxian!=b.youxian)
15                         return a.youxian>b.youxian;
16                             return a.shijian>b.shijian;
17                     }
18 };
19 int main()
20 {
21     priority_queue< que, vector<que>, cmp > p;
22     char s[20],a[20];
23     que aa;
24     int c,y,o=0;
25     while(~scanf("%s",&s)){o++;
26         if(s[0]=='P'){
27             scanf("%s",&aa.str);
28             scanf("%d%d",&aa.canshu,&aa.youxian);
29             aa.shijian=o;
30             p.push(aa);
31         }else{
32             if(p.empty())
33                 printf("EMPTY QUEUE!\n");
34             else{
35                 aa=p.top();
36                 printf("%s %d\n",aa.str,aa.canshu);
37                 p.pop();
38             }
39         }
40     }
41     return 0;
42 }
View Code

 

 

F;

最小的n个和
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 17(8 users) Total Accepted: 6(5 users) Rating:  Special Judge: No
Description

给定A、B两个数列,各包含n个数,分别从A和B中任意取一个数相加得到和,这样会有n^2种结果(包括重复的),求n^2个结果中前n个最小的和。

 

Input

有多组测试数据。

对于每组测试数据,第一行为n,第二行为数列A,第三行为数列B。

1<=n<=100000, 0 <= Ai, Bi <= 10^9。

Output

对于每组测试数据,输出一行,包含前n个最小的和,按照升序输出,两数之间用一个空格隔开。

Sample Input
5
1 3 4 2 0
7 3 5 2 11
10
74 50 47 45 38 64 19 2 84 69
91 46 44 7 67 1 40 60 78 41
Sample Output
2 3 3 4 4
3 9 20 26 39 42 43 45 46 46
Source
HCPC2014校赛训练赛 3

比赛的时候没做出来,现在做出来了:

代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<stdio.h>
 5 using namespace std;
 6 
 7 const int maxn=100005;
 8 int a[maxn],b[maxn],c[maxn];
 9 
10 int main()
11 {
12     int n;
13     //freopen("aa.txt","r",stdin);
14     while(scanf("%d",&n)!=EOF)
15     {
16         for(int i=0;i<n;i++)
17         scanf("%d",&a[i]);
18         for(int i=0;i<n;i++)
19         scanf("%d",&b[i]);
20         sort(a,a+n);
21         sort(b,b+n);
22         for(int i=0;i<n;i++)
23         c[i]=a[0]+b[i];
24         make_heap(c,c+n);
25         for(int i=1;i<n;i++)
26         {
27             for(int j=0;j<n;j++)
28             {
29                 int x=a[i]+b[j];
30                 if(x<c[0])
31                 {
32                     pop_heap(c,c+n);
33                     c[n-1]=x;
34                     push_heap(c,c+n);
35                 }
36                 else
37                 break;
38             }
39         }
40         sort_heap(c,c+n);
41         for(int i=0;i<n;i++)
42         printf(i==0?"%d":" %d",c[i]);
43         printf("\n");
44     }
45     return 0;
46 }
View Code

 

posted @ 2014-03-18 15:35  悠悠我心。  阅读(338)  评论(0编辑  收藏  举报