I am a teacher!

导航

C语言程序设计100例之(79):女孩节

例79   女孩节

问题描述

在女孩节,我们班上男生和女生聚在一起。在这个场合,每个男孩都会为女孩许愿。男孩想知道女孩对他们愿望的反应。

如果一个愿望包含一个或多个女孩的名字,它被认为是与她们特别交谈。否则它就是在和所有的女孩说话。当然,一个愿望可以同时与几个女孩交谈。

如果愿望最多包含9个单词,女孩会说“oh”。

如果愿望至少包含10个单词,并且愿望中包括“beautiful”、“pretty”或“lovely”等单词,女孩会说“xixi”。

如果愿望至少包含10个单词,但愿望中没有出现上面提到的3个单词,女孩会说“hehe”。

一个愿望中不会包含所有的女孩的名字。

输入

输入的第一行包含两个整数g和w(1<=g<=5,1<=w<=30),分别是女孩数量和愿望数量。接下来的g行中,每行是一个只含小写单词的单词,代表一个女孩的名字。接下来的w行中,每行是一个愿望,一个愿望最多包含200个字符,字符只包括字母、空格和“!”。每个愿望包含一个或多个句子,每个句子以“!”结尾。每个句子的第一个字母都是大写的,其他字母总是小写的。你可以假设每个愿望在语法上都是正确的。

输出

对于输入的每个愿望,给出女孩的回答。如果它正在与所有女孩交谈,输出“All”,或者按照女孩在姓名列表中出现的顺序,输出该愿望涉及的女孩列表(姓名之间用一个空格分隔)。然后输出一个分号,后面跟一个空格,以及诸如“hehe”、“xixi”、“oh”之类的反应。

输入样例

5 5

answer

baiqingr

cedar

juleo

seven

Happy girls day to all of you!

Happy girls day to all of you!Wish you happy forever!

Happy girls day for answer mm!

Congratulations for cedar mm and seven mm!Wish you more and more beautiful hehe!

Hello answer hello baiqingr hello juleo would you mind having dinner together!

输出样例

All: oh

All: hehe

answer: oh

cedar seven: xixi

answer baiqingr juleo: hehe

        (1)编程思路。

        因为要检查beautifulpretty“lovely等单词在愿望中的出现情况,编写函数int find(char *a,char *b)检查作为单词b的字符串是否在字符串a中出现,与一般字符串匹配略有不同的是,若b在a中出现,还需看匹配的前后是否有1个空格,或匹配之前有空格,之后有“!”符号。

        编写好函数后,直接按题意进行模拟处理即可。

        (2)源程序。
#include<stdio.h>
#include <string.h>
int find(char *a,char *b)
{
    int alen=strlen(a);
    int blen=strlen(b);
    int i,j;
    for (i=0;i<alen;i++)
    {
        for (j=0;j<blen && (i+j)<alen; j++)
        {
            if (b[j]!=a[i+j])
                break;
        }
        if (i!=0 && j==blen && (a[i-1]==' '||a[i-1]=='!') && (a[i+j]==' '||a[i+j]=='!'))
            return 1;
        if (i==0 && j==blen && (a[i+j]==' '||a[i+j]=='!'))
            return 1;
    }
    return 0;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    char name[6][25];
    int i;
    for (i=0;i<n;i++)
       scanf("%s",name[i]);
    getchar();
    while (m--)
    {
        char wish[205];
        gets(wish);
        int wordnum=0;                           // 单词数
        for (i=0;wish[i]!='\0';i++)
        {
            if (wish[i]>='A' && wish[i]<='Z')   // 大写变小写
                wish[i]=wish[i]-'A'+'a';
            if (wish[i]>='a'&& wish[i]<='z' && (wish[i+1]==' '||wish[i+1]=='!'))
                wordnum++;
        }
        int h[6];
        memset(h,0,sizeof(h));
        int cnt=0;
        for (i=0;i<n;i++)
        {
            if (find(wish,name[i]) && h[i]==0)
            {
                h[i]=1;
                cnt++;
            }
        }
        if (cnt==0)
            printf("All: ");
        else
        {
            int f=0;
            for (i=0;i<n;i++)
            {
                if (h[i]==1)
                {
                    if (f==0)
                    {
                        printf("%s",name[i]);
                        f=1;
                    }
                    else
                    {
                        printf(" %s",name[i]);
                    }
                }
            }
            printf(": ");
        }
        if (wordnum<=9)
            printf("oh\n");
        else
        {
            if (find(wish,"beautiful") || find(wish,"pretty") || find(wish,"lovely"))
                printf("xixi\n");
            else
                printf("hehe\n");
        }
    }
    return 0;
}

        将此源程序提交给北大OJ题库 POJ 1677 Girls' Day(http://poj.org/problem?id=1677)可以Accepted。

习题79

79-1  拼写检查

问题描述

现在有一些英语单词需要做拼写检查,你的工具是一本词典。需要检查的单词,有的是词典中的单词,有的与词典中的单词相似,你的任务是发现这两种情况。单词A与单词B相似的情况有三种:

1、删除单词A的一个字母后得到单词B;

2、用任意一个字母替换单词A的一个字母后得到单词B;

3、在单词A的任意位置增加一个字母后得到单词B。

你的任务是发现词典中与给定单词相同或相似的单词。

输入

第一部分是词典中的单词,从第一行开始每行一个单词,以"#"结束。词典中的单词保证不重复,最多有10000个。

第二部分是需要查询的单词,每行一个,以"#"结束。最多有50个需要查询的单词。

词典中的单词和需要查询的单词均由小写字母组成,最多包含15个字符。

输出

按照输入的顺序,为每个需要检查的单词输出一行。如果需要检查的单词出现在词典中,输出“?x is correct",?x代表需要检查的单词。如果需要检查的单词没有出现在词典中,则输出"?x: ?x1 ?x2 ...?xn",其中?x代表需要检查的单词,?x1...?xn代表词典中与需要检查的单词相似的单词,这些单词中间以空格隔开。如果没有相似的单词,输出"?x:"即可。

输入样例

i

is

has

have

be

my

more

contest

me

too

if

award

#

me

aware

m

contest

hav

oo

or

i

fi

mre

#

输出样例

me is correct

aware: award

m: i my me

contest is correct

hav: has have

oo: too

or:

i is correct

fi: i

mre: more me

         (1)编程思路。

        设给定单词的长度为len,则词典中与给定单词相同或相似的单词的长度只可能为len-1、len或len+1,分别对词典中字符串长度为这三种情况的单词进行处理。

        (2)源程序。

#include <stdio.h>
#include <string.h>
int main()
{
    int i,j,x,k;
    char s[10001][18];
    for(i=0; ;i++)
    {
       scanf("%s",s[i]);
       if (strcmp(s[i],"#")==0)
          break;
    }
    int n=i;
    char str[18],ans[10001][18];
    while (scanf("%s",str) && strcmp(str,"#")!=0)
    {
       int f=0;
       int cnt=0;
       for (i=0; i<n; i++)
       {
          if (strcmp(s[i],str)==0)
          {
              printf("%s is correct\n",str);
              break;
          }
       }
       if (i<n) continue;
       for (i=0; i<n; i++)
       {
          if((strlen(s[i])-strlen(str))==1)
          {
              x=0;
              for(j=0,k=0; j<strlen(s[i])&& k<strlen(str); k++,j++)
              {
                  while(s[i][j]!=str[k]&&(k<strlen(str))&&(j<strlen(s[i])))
                  {
                     if(x==0)
                        j++;
                     if(x!=0)
                        k++;
                     x++;
                  }
               }
               if(x<=1)
               {
                  f=1;
                  strcpy(ans[cnt++],s[i]);
               }
          }
          if((strlen(s[i])-strlen(str))==-1)
          {
               x=0;
               for(j=0,k=0; j<strlen(s[i])&& k<strlen(str); k++,j++)
               {
                   while(s[i][j]!=str[k]&&(k<strlen(str))&&(j<strlen(s[i])))
                   {
                      if(x==0)
                          k++;
                      if(x!=0)
                          j++;
                      x++;
                   }
               }
               if(x<=1)
               {
                    f=1;
                    strcpy(ans[cnt++],s[i]);
               }
           }
           if((strlen(s[i])-strlen(str))==0)
           {
               x=0;
               for(j=0; j<strlen(str); j++)
               {
                   if(s[i][j]!=str[j])
                   {
                       x++;
                   }
               }
               if(x==1)
               {
                   f=1;
                   strcpy(ans[cnt++],s[i]);
               }
           }
       }
       printf("%s:",str);
       if (f)
          for(i=0; i<cnt; i++)
          {
             printf(" ");
             printf("%s",ans[i]);
          }
       printf("\n");
     }
     return 0;
 }

        将此源程序提交给北大OJ题库 POJ 1035 Spell checker(http://poj.org/problem?id=1035)可以Accepted。

79-2  字谜组

问题描述

给定一个文本,找出其中5个最大的字谜组。

文本中包括一系列单词。一个单词w是一个单词v的一个变位词,当且仅当将w中的一些字符位置重新排列得到v。我们称w和v在同一个字谜组中。字谜组的大小是该组中的单词数。

输入

输入包含由小写字母组成的单词,由空格(或新行)分隔。它由EOF终止。你可以假设不超过30000个单词。

输出

输出5个最大的字谜组。如果少于5组,则将其全部输出。按大小对组进行排序。组内单词按字典顺序进行排序,相同的单词只输出一个,组间也按第1个单词的字典顺序排列。

输入样例

undisplayed

trace

tea

singleton

eta

eat

displayed

crate

cater

carte

caret

beta

beat

bate

ate

abet

输出样例

Group of size 5: caret carte cater crate trace .

Group of size 4: abet bate beat beta .

Group of size 4: ate eat eta tea .

Group of size 1: displayed .

Group of size 1: singleton .

        (1)编程思路。

        定义结构体数组word来保存输入的各个单词。

struct WordNode

{

    char org[80];

    char ord[80];

}word[30005];

        其中,成员分量org保存输入的单词的原始字符串,ord保存将输入的单词按小写字母从小到大排列后的字符串。若单词w和v在同一个字谜组中,则单词w和v的成员分量ord字符串一定相同。

再定义结构体数组group保存各字谜组。

struct GroupNode

{

    int num;

    int start;

}group[30005];

        其中,成员分量num保存字谜组中单词个数,start保存字谜组中第1个单词在排好序后的word数组中的下标位置。

        程序中主要进行3个排序,输入一个单词后,将每个单词按小写字母从小到大排列后的保存到成员分量ord字符串中。

        全部单词输入完后,将单词数组word按成员分量ord字典序升序排列,这样同一字谜组中的单词一定排在一起,若成员分量ord相同,则按单词的原始形式org按字典序升序排列。这样,word数组按字谜组排列,组内单词也按字典序排列。

        对word数组进行循环遍历,将每个字谜组的情况统计并保存到group数组中,之后将group数组按成员分量num降序排列,这样字谜组中单词个数多的排在前面,若成员分量num相同,则按start升序排列,从而保证组间也按第1个单词的字典顺序排列。

      (2)源程序。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct WordNode
{
    char org[80];
    char ord[80];
}word[30005];
struct GroupNode
{
    int num;
    int start;
}group[30005];
int cmp1(struct WordNode a, struct WordNode b)
{
    if (strcmp(a.ord, b.ord) != 0)
        return strcmp(a.ord, b.ord) < 0;
    return strcmp(a.org, b.org) <= 0;
}
int cmp2(struct GroupNode a, struct GroupNode b)
{
    if (a.num != b.num)
        return a.num > b.num;
    return strcmp(word[a.start].org, word[b.start].org)<=0;
}
int main()
{
    int n=0;                 // 单词个数
    int i,j;
    while(scanf("%s", word[n].org) != EOF)
    {
        strcpy(word[n].ord, word[n].org);
        int len = strlen(word[n].ord);
        sort(word[n].ord, word[n].ord + len);
        n++;
    }
    sort(word, word+n,cmp1);
    int cnt=1;              // 当前组数
    group[0].start = 0;    // 第1个单词肯定在第1组中
    group[0].num = 1;
    for (i=1; i<n; i++)
    {
        if (strcmp(word[i].ord, word[group[cnt-1].start].ord)==0)
        {
            group[cnt-1].num++;
        }
        else
        {
            group[cnt].start = i;
            group[cnt].num = 1;
            cnt++;
        }
    }
    sort(group, group + cnt, cmp2);
    for (i=0; i<5; i++)
    {
        printf("Group of size %d: ",group[i].num);
        int p=group[i].start;
        printf("%s ", word[p].org);
        for (j=1; j<group[i].num; j++)
        {
            if(strcmp(word[p+j].org,word[p+j-1].org)!=0)
            {
                printf("%s ", word[p+j].org);
            }
        }
        printf(".\n");
    }
    return 0;
}

        将此源程序提交给北大OJ题库 POJ 2408 Anagram Groups(http://poj.org/problem?id=2408)可以Accepted。

79-3  单词翻译

问题描述

你刚从伦敦搬到一个大城市。这里的人说一种难以理解的外语方言。幸运的是,你有一本字典来帮助你理解它们。

输入

输入由多达100000个字典条目组成,后面是一个空行,后面是多达100000个单词的消息。每个字典条目都是一行,包含一个英语单词,后跟一个空格和一个外语单词。在字典中,外语单词不会出现一次以上。输入中的每个单词最多由10个小写字母组成。

输出

将输入的外语单词翻译成英语单词,每行一个单词。字典里没有的外语单词应该翻译成“eh”。

输入样例

dog ogday

cat atcay

pig igpay

froot ootfray

loops oopslay 

atcay

ittenkay

oopslay

输出样例

cat

eh

loops

        (1)编程思路。

定义结构体数组word来保存字典。

struct Dictionary

{

    char e[15];

    char s[15];

} word[100001];

其中,成员分量e保存英文单词,s保存外语单词。

将字典word按外语单词升序排列。

        之后,对于每个查找的外语单词,采用二分法对数组word进行查找,若查找成功,输出对应的英语单词,若不成功,输出字符串“eh”。

      (2)源程序。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n;
struct Dictionary
{
    char e[15];
    char s[15];
};
struct Dictionary word[100001];
int cmp(struct Dictionary a,struct Dictionary b)
{
    return strcmp(a.s,b.s)<0;
}
int judge(char *s)
{
    int left=0,right=n-1;
    while (left<=right)
    {
       int mid=(left+right)/2;
       if (strcmp(word[mid].s,s)==0)
           return mid;
       else if (strcmp(word[mid].s,s)>0)
           right=mid-1;
       else
           left=mid+1;
    }
    return -1;
}
int main()
{
    n=0;
    char c;
    char s[15];
    while(scanf("%s%c",word[n].e,&c)!=EOF)
    {
        if(c=='\n')
        {
            strcpy(s,word[n].e);
            break;
        }
        scanf("%s",word[n].s);
        n++;
    }
    sort(word,word+n,cmp);
    int k=judge(s);
    if(k>=0)
       printf("%s\n",word[k].e);
    else
       printf("eh\n");
    while(scanf("%s",s)!=EOF)
    {
       k=judge(s);
       if (k>=0)
          printf("%s\n",word[k].e);
       else
          printf("eh\n");
    }
    return 0;
}

        将此源程序提交给北大OJ题库 POJ 2503 Babelfish(http://poj.org/problem?id=2503)可以Accepted。

posted on 2022-03-14 06:26  aTeacher  阅读(344)  评论(0编辑  收藏  举报