poj.1035

来源:互联网 发布:exchange的域名是什么 编辑:程序博客网 时间:2024/05/01 17:59

这个题目的意思很明确,就是给定一个自定义的串集合,相当于字典,然后给定一连串的检查字符串,要求判断字符串是否在字典中,若在则输出correct,否则对其进行改正,改正的方式共有三种:

1)删除一个字符(任意位置)

2)修改一个字符(任意位置,任意的小写字母)

3)插入一个字符(任意位置,任意的小写字母)

要求改正后的串要在字典中存在,且字典中的串不重复。思路很清晰,首先是保存输入,然后对每个检查字符进行判断,若不为正确字符则对其进行相应的修改,开始时我用了一个最直接也最费时间的算法对每个串都进行所有可能的判断,结果明显超时了,后来,看了一些别人的代码,对别了一下,发现,别人写的的却要简化了许多,我原本写的时间复杂度为O(26*15*15*lens*lent),而对方写的为o(lens*lent),其中lens为字典中串的个数,lent为需要检查的串个数。下面是我超时的代码:

#include <stdio.h>#include <stdlib.h>#include <cstring>#define sMax 10010#define tMax 60struct Source{int len;char str[20];bool trag;}s[sMax],t[tMax];bool vi[26];int lens,lent;bool Is_right(char *p,int n){for(int i=0;i<lens;i++)if(n==s[i].len)if(strcmp(s[i].str,p)==0){s[i].trag=1;return 1;}return 0;}int main(){int index=0,pivot;char st,inst;memset(vi,0,sizeof(vi));while(true){st=getchar();if(st=='#')break;vi[st-'a']=1;pivot=0;s[index].str[pivot++]=st;while(true){inst=getchar();if(inst=='\n')break;vi[inst-'a']=1;s[index].str[pivot++]=inst;}s[index].len=pivot;s[index].str[pivot]='\0';index++;}lens=index;index=0;getchar();while(true){st=getchar();if(st=='#')break;pivot=0;t[index].str[pivot++]=st;while(true){    inst=getchar();if(inst=='\n')break;t[index].str[pivot++]=inst;}t[index].len=pivot;t[index].str[pivot]='\0';index++;}lent=index;int i,j,k,w;char temp[20];    for(i=0;i<lent;i++){if(Is_right(t[i].str,t[i].len)){printf("%s is correct\n",t[i].str);continue;}for(j=0;j<lens;j++)s[j].trag=0;//replaceprintf("%s:",t[i].str);for(j=0;j<t[i].len;j++){char ind=t[i].str[j];for(k=0;k<26;k++){if(!vi[k])continue;//for(w=0;w<=t[i].len;w++)//temp[w]=t[i].str[w];if(t[i].str[j]!='a'+k){//temp[j]='a'+k;t[i].str[j]='a'+k;Is_right(t[i].str,t[i].len);}}t[i].str[j]=ind;}//deletefor(j=0;j<t[i].len;j++){int px=0;for(k=0;k<t[i].len;k++){if(k==j){px=j;    continue;}temp[px++]=t[i].str[k];}temp[px]='\0';Is_right(temp,t[i].len-1);}//insertfor(j=0;j<26;j++){if(!vi[j])continue;for(k=0;k<=t[i].len;k++){for(w=0;w<=k-1;w++)temp[w]=t[i].str[w];temp[w]=j+'a';for(w=k;w<t[i].len;w++)temp[w+1]=t[i].str[w];temp[w+1]='\0';    Is_right(temp,t[i].len+1);}}for(j=0;j<lens;j++)if(s[j].trag) printf(" %s",s[j].str);printf("\n");}    return 0;}

下面是ac代码:

#include <stdio.h>#include <stdlib.h>#include <cstring>#define Max 10010char s[Max][16];char t[60][16];int lens,lent;int wids[Max];int widt[60];int address[Max];void Input(){int index=0,pivot;char st;while(true){st=getchar();if(st=='#')break;pivot=0;s[index][pivot++]=st;while(true){st=getchar();if(st=='\n')break;s[index][pivot++]=st;}s[index][pivot]='\0';wids[index]=pivot;index++;}lens=index;getchar();index=0;while(true){st=getchar();if(st=='#')break;pivot=0;t[index][pivot++]=st;while(true){st=getchar();if(st=='\n')break;t[index][pivot++]=st;}t[index][pivot]='\0';widt[index]=pivot;index++;}lent=index;}bool change(char *p,char *q){int dif=0;for(;*p;p++,q++)if(*p!=*q)dif++;if(dif==1) return true;return false;}bool dete(char *p,char *q){int dif=0;for( ;*q; )if(*p!=*q){dif++;q++;continue;}else{p++;q++;}if(dif==1)return 1;return 0;}bool insert(char *p,char *q){if(dete(q,p))return 1;return 0;}int main(){    Input();int i,j,index;bool trag;for(i=0;i<lent;i++){trag=0;index=0;for(j=0;j<lens;j++){if(widt[i]==wids[j]){if(strcmp(s[j],t[i])==0){printf("%s is correct\n",t[i]);trag=1;break;}    else if(change(s[j],t[i]))address[index++]=j;}else if(widt[i]-1==wids[j]){if(dete(s[j],t[i])) address[index++]=j;}else if(widt[i]+1==wids[j]){if(insert(s[j],t[i])) address[index++]=j;}}if(!trag){printf("%s:",t[i]);for(int k=0;k<index;k++)printf(" %s",s[address[k]]);printf("\n");}}return 0;}

反思了一下,发现自己为什么会比较慢,因为我是对串中的每个字符都做了三种修改,而且将修改的所有可能都考虑进去了,很全面,但是相应的会包含一些根本不可能也没有必要的比较,简单的思路应该是这样的:对每个带检查的串,首先判断是否为正确的串,若是则直接输出,若不是,则枚举字典中所有的串,每一个串只有四种可能,要么是上述三种修改中的一种,要么都不是,这样就可以达到o(lent*lens)的时间复杂度了。其实归根结底还是判断是否为修改错误的三种情况函数的简化情况不一样。

0 0