AStar百度之星2008初赛题目总结2.1:成语纠错 (15分)

本文介绍了一个成语纠错算法的具体实现过程,包括如何通过比对输入的错误成语与标准成语库来找到正确的成语,同时确保修改的字符位于同一汉字分类中。文章详细解释了算法步骤并提供了参考代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题背景

成语是中华民族的文化瑰宝,作为历史的缩影、智慧的结晶、汉语言的精华,闪烁着睿智的光芒。
你的任务是给一个错误的四字成语进行纠错,找到它的正确写法。具体来说,你只允许修改四个汉字中的其中一个,使得修改后的成语在给定的成语列表中出现。原先的错误成语保证不在成语列表中出现。

有时,这样的纠错结果并不惟一。例如一糯千金可以改为一字千金也可以改成一诺千金。但由于是同音字,一糯千金实为一诺千金的可能性比较大。
因此,我们还将提供一个汉字分类表,要求修改前后的两个字必须属于同一个分类。
在这样的限制下,我们保证成语纠错的结果惟一。

注意

1、汉字均采用GBK编码(参见FAQ)
2
、每个汉字分类至少包含两个汉字,同一个汉字可能出现在多个类别中。
3
、成语列表中的成语都是真实存在的四字成语。成语列表和待纠错成语中的所有汉字均在汉字分类表中的至少一个分类中出现。

输入格式

输入第一行包含两个整数n, m(1<=n<=200, 1<=m<=20000)n表示汉字类别的个数,m表示成语的个数。
以下n行每行用一个无空白分隔符(空格、TAB)的汉字串表示一个分类中的所有汉字。注意,该汉字串最多可能包含200个汉字。

以下m行为成语列表,每行一个成语,恰好四个汉字。
最后一行为待纠错的成语,恰好四个汉字,且不在成语列表中出现。

输出格式

仅一行,为一个四字成语。在修改必须在同一分类中进行的限制下,输入数据保证纠错结果惟一。

样例输入

7 3
糯诺挪喏懦

字自子紫籽
前钱千牵浅
进近今仅紧金斤尽劲
完万
水睡税
山闪衫善扇杉
一诺千金
一字千金
万水千山
一糯千金

样例输出

一诺千金

解题思路

1、把汉字分类和正确成语分别放在字符串数组中,待纠错成语放在字符串里
2、把带纠错成语对应的正确成语找出来
3、对比找出待纠错成语中错的那个字,并保存错字位置索引
4、找到错字所属的汉子类别,并保存类别的位置索引
5、根据错字的位置,判断正确成语相应位置的字是否在正确的汉字类别中,确定正确的成语输出

【评价】这个题是第一题,我使用的方法是按部就班的进行搜索计算,没有太多的技巧,关键是把题目分析清楚。

参考代码:

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <string.h>

int main(void)
{
 int n(0);//汉字类别个数 1-200
 int m(0);//正确成语个数1-20000
 int i(0),j(0);//循环变量
 int *tempLen;//汉字类的串长
 char** pClass=NULL;//存放汉字分类
 char classBuffer[401];//缓存
 
 char** pIdiom=NULL;//存放正确成语
 char idiomBuffer[9];//缓存

 char** pSet=new char*[200];//和待纠错成语有三个字相同的正确成语集合

 char wrongString[9];//存放待纠错成语

 scanf("%d",&n);
 pClass=new char*[n];//n类
 tempLen=new int[n];//长度

 scanf("%d",&m);
 pIdiom=new char*[m];//m个成语

 //读汉字分类
 for (i=0;i<n;i++)
 { 
  scanf("%s",classBuffer);
  tempLen[i]=strlen(classBuffer);
  pClass[i]=new char[tempLen[i]+1];
  memcpy(pClass[i],classBuffer,tempLen[i]+1);
 }
 //读正确成语
 for (i=0;i<m;i++)
 {
  scanf("%s",idiomBuffer);
  pIdiom[i]=new char[9];
  memcpy(pIdiom[i],idiomBuffer,9);
 }

 //读待纠错成语
 scanf("%s",wrongString);
 //--------读取数据完毕-------------
 //把带纠错成语对应的正确成语找出来
 int diffcount=0;//每个成语中不同的汉字个数
 int count=0;//计数
 for (i=0;i<m;i++)
 {
  diffcount=0;  
  for (j=0;j<4;j++)
  {
   if (diffcount>=2)
   {
    break;
   }
   else
   {
    if(pIdiom[i][2*j]!=wrongString[2*j] || pIdiom[i][2*j+1]!=wrongString[2*j+1])
    {
     //不同的汉字
     diffcount++;
    }
   }
  }
  
  if (diffcount==1)//只有一个字不同的成语找出来
  {
   pSet[count]=new char[9];
   memcpy(pSet[count],pIdiom[i],9);
   count++;
  }
  }
 //找出待纠错成语中错的那个字
 char wrongChar[2];//放错字
 int charIndex(0);//错字的索引
 for (i=0;i<4;i++)
 {
  if (!(wrongString[2*i]==pSet[0][2*i] && wrongString[2*i+1]==pSet[0][2*i+1]))
  {
   charIndex = i;
   wrongChar[0]=wrongString[2*i];
   wrongChar[1]=wrongString[2*i+1];
   break;
  }
 }
 //找到错字所属的汉子类别
 int classIndex(0);//存放正确汗字类的索引
 bool find=false;//找到这个错字
 for (i=0;i<n;i++)
 {
  tempLen[i] = tempLen[i]>>1;//右移除以2
  for (j=0;j<tempLen[i];j++)
  {
   if (wrongChar[0]==pClass[i][2*j] && wrongChar[1]==pClass[i][2*j+1])
   {
    classIndex = i;
    find = true;
    break;
   }
  }
  if (find)
  {
   break;
  }
 }
 //找到可纠正位置的汉字和错字所属类相同的正确成语,输出
 for (i=0;i<count;i++)
 {
  for (j=0;j<tempLen[classIndex];j++)
  {
   if (pSet[i][2*charIndex]==pClass[classIndex][2*j] && pSet[i][2*charIndex+1]==pClass[classIndex][2*j+1])
   {
    printf("%s",pSet[i]);//输出正确成语
    break;
   }
  }
 }
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值