- 还活着,全是补题
A - 神奇的皮卡丘
本题只有一组数据,所有单词只包含小写字母。测试用例由两部分组成,字典部分以一个单行字符串“START”开头,此字符串应该被忽略。然后下面每行包含两个单词,第一个是英文单词,第二个是皮卡丘的语言。字典以一个单行字符串“END”结束。字典不包含“START”和“END”。皮卡丘的文章同样以“START”开头,以“END”结束,然后是一篇皮卡丘写的文章。你应该将文章翻译成英文。如果你在字典中找到该单词,则应将其翻译并将新单词写入你的翻译,如果你无法在字典中找到该单词,则无需翻译它,只需将旧单词复制到你的翻译中即可。空格,制表符和回车及所有标点符号不应该被翻译。每行最多包含3000个字符
字典树的题,map也可以做,而且代码短。暂且不说字典树,再熟悉熟悉补上。
- MAP做法
#include<iostream>
#include<string.h>
#include<map>
#include<cstdio>
using namespace std;
map<string,string>M;
int main()
{
string a,b;
cin >> a;//"START"
while(cin>>a && a!="END")
{
cin>>b;
M[b] = a;
}
cin>>a;//"START"
getchar();//吃回车
char tmp[3005];
while(1)
{
gets(tmp);
if(strcmp(tmp,"END") == 0 )
break;
int len = strlen(tmp);
b = "";
for(int i=0; i<len; i++)
{
if(!(tmp[i]>='a' && tmp[i]<='z'))//如果非小写字母就要考虑空格,表店之类的啦
{
if(M[b]!="")//存在这个单词
cout<<M[b];
else
cout<<b;
b="";
cout<<tmp[i]<<"***";//输出这个空格,标点之类的。。
}
else //小写字母
b+=tmp[i];
}
cout<<endl;
}
return 0;
}
B - 拯救学长
就给你N个排成一行的金字塔,金字塔是椎体,底面都是正方形,给你每个金字塔的高H,和底面正方形的边长L,求出一个合适的高度h,让屠龙宝刀按这个高度平行于地平线,把一排的金字塔切成上下两部分,使上半部分的体积之和等于下半部分的体积之和。”
二分法的题,从TL到WA,整数型的二分模板和浮点型的真的不一样。。。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>//这个G++才识别,vj就别用C++判断了
#define EPS 1e-5
using namespace std;
const int mx = 11010;
double x[mx], h[mx];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
double r=0;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lf",&h[i]);
r=max(r,h[i]);//为了节省时间啊啊
}
double v=0;
for(int j=0; j<n; j++)
{
scanf("%lf",&x[j]);
v+=x[j]*x[j]*h[j]/3;//记录总体积
}
double l=0;
while(r-l>EPS)//大概错在这里。。。
{
double mid=(l+r)/2;
double vv=0;
for(int j=0; j<n; j++)
{
if(h[j]>mid)
vv+=(h[j]-mid)*(h[j]-mid)*(h[j]-mid)*x[j]*x[j]/h[j]/h[j]/3;
}
if(vv*2>v)
l=mid;
else
r=mid;
}
printf("%d\n",(int)(l+EPS));
}
return 0;
}
C - e-KMP
求S1的前缀和S2的后缀的《最大》匹配
看都没来得急看。。沉溺debug无法自拔。。
把s1和s2连接,用一个KMP模板里的next数组,直接找最长前后缀就可以,注意s1=aaa, s2=aaaa这种情况。
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
char a[100005],b[50005];
int nextt[100005],len,len1,len2;
void getnextt()//常用模板啊
{
int j=0, k=-1;
nextt[0] = -1;
while(j < len)
{
if(k == -1 || a[j] == a[k])
{
j++;
k++;
nextt[j] = k;
}
else k = nextt[k];
}
}
int main()
{
while(~scanf("%s%s",a,b))//或用EOF
{
len1=strlen(a),len2=strlen(b),len=len1+len2;
strcat(a,b);
getnextt();
int j=nextt[len];
while(j>len1||j>len2)
j=nextt[j]; //防止aaa aaaa这种情况
for(int i=0; i<j; i++)//有的话把找到的前(后)缀也输出来
printf("%c",a[i]);
if(j)
printf(" ");
printf("%d\n",j);
}
}
- 记一个有点小差异的getnext模板
void getnextt()//稍稍有些区别的next数组写法
{
//memset(nextt,0,sizeof(nextt));
nextt[0]=0,nextt[1]=0;
for(int j=1; j<len; j++)
{
int k=nextt[j];
while(k&&a[j]!=a[k])
k=nextt[k];
if(a[j]==a[k])
nextt[j+1]=k+1;
else
nextt[j+1]=0;
}
}
E - 皮皮的字符串
皮皮手上有若干个字符串s1,他现在想得到一种字符串s2, 这种字符串(s2)的定义是这样的:给定两个字符串s1和s2,如果能通过s1循环移位,使s2包含在s1中,那么s2就是皮皮需要的字符串。现在皮皮找到了若干可能的字符串s2,现在他拜托聪明的你帮他编写程序看看是不是皮皮需要的字符串,如果是则输入yes,不是则输出no
把s1直接翻倍,然后按KMP找子串的模板做。
至于为什么原来的那个写法有bug,暂时还是没想好。。
#include<stdio.h>
#include<string.h>
#define maxn 100005
int nextt[maxn],lenx,leny;
char x[maxn],y[maxn];
void get_nextt()
{
int i=0,j=-1;
nextt[0]=-1;
while(i<lenx)
{
if(j==-1||x[i]==x[j])
{
++i;++j;
nextt[i]=j;
}
else
{
j=nextt[j];
}
}
}
void kmp()
{
get_nextt();
int i=0,j=0;
while(i<2*leny)//二倍之内就可以匹配所有情况
{
if(j==-1||x[j]==y[i%leny])//取余就处理了循环的情况
{
++i;++j;
if(j==lenx)
{
printf("yes\n");
return;
}
}
else
{
j=nextt[j];
}
}
printf("no\n");
}
int main()
{
while(gets(y))
{
gets(x);
lenx=strlen(x);
leny=strlen(y);
kmp();
}
return 0;
}