1035:拼写检查
总时间限制: 2000ms 内存限制: 65536kB
描述
现在有一些英语单词需要做拼写检查,你的工具是一本词典。需要检查的单词,有的是词典中的单词,有的与词典中的单词相似,你的任务是发现这两种情况。单词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
解答:
【标记】 记str[10000]用来存储字典,count为字典内单词总数。k、i、j分别代表求编辑距离时字典单词编号、字典单词前i个字符、测试用例前j个字符。dp[i][j]表示取字典单词前i个字符、测试用例前j个字符时的编辑距离。char temp[20]为输入,in表示temp转换为string。x表示终止时的"#",dis是最终的编辑距离,
【思路】用map存储字典,对每一个测试用例,如果map中有它对应的int,就说明是correct的。否则的话,针对当前测试用例,遍历所有字典单词,求当前用例与字典单词的编辑距离,如果编辑距离是1,就是相似单词。
【注意】编辑距离初始化、求三个值的min
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
std::map<string,int> m;
struct ss
{
string s;
}str[10000];
int main(int argc, char const *argv[])
{
string in,x;
int count,i,j,k,dis,dp[20][20],p;
char temp[20];
x="#";
count=0;
while(scanf("%s",&temp))
{
in=temp;
if(x==in)break;
m[in]=1;
str[count++].s=in;
}
while(scanf("%s",&temp))
{
in=temp;
if(x==in)break;
if(m[in]==1)
cout<<in<<" is correct"<<endl;
else
{
cout<<in<<":";
//对每一个测试用例求编辑距离
for(k=0;k<count;k++)
{
//初始化编辑距离dp
for(i=0;i<=str[k].s.size();i++) dp[i][0]=i;
for(j=0;j<=in.size();j++)dp[0][j]=j;
dis=0;
//求编辑距离
for(i=1;i<=str[k].s.size();i++)
{
for(j=1;j<=in.size();j++)
{
if(str[k].s[i-1]==in[j-1])dp[i][j]=dp[i-1][j-1];
else
{
p=min(dp[i-1][j],dp[i][j-1]);
dp[i][j]=min(p,dp[i-1][j-1])+1;
}
}
}
dis=dp[str[k].s.size()][in.size()];
if(dis==1)
cout<<" "<<str[k].s;
}
printf("\n");
}
}
return 0;
}