ACM新手周赛 2

  • 还活着,全是补题

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;
}
发布了47 篇原创文章 · 获赞 4 · 访问量 1308

猜你喜欢

转载自blog.csdn.net/listenhhh/article/details/97621281
今日推荐