问题背景
成语是中华民族的文化瑰宝,作为历史的缩影、智慧的结晶、汉语言的精华,闪烁着睿智的光芒。
你的任务是给一个错误的四字成语进行纠错,找到它的正确写法。具体来说,你只允许修改四个汉字中的其中一个,使得修改后的成语在给定的成语列表中出现。原先的错误成语保证不在成语列表中出现。
有时,这样的“纠错”结果并不惟一。例如“一糯千金”可以改为“一字千金”也可以改成“一诺千金”。但由于“糯”和“诺”是同音字,“一糯千金”实为“一诺千金”的可能性比较大。
因此,我们还将提供一个汉字分类表,要求修改前后的两个字必须属于同一个分类。
在这样的限制下,我们保证成语纠错的结果惟一。
注意
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;
}
文章出处:http://www.diybl.com/course/3_program/c++/cppsl/200863/120780.html