POJ 1035 Spell checker(串)
题目网址:http://poj.org/problem?id=1035
思路:
看到题目第一反应是用LCS ——最长公共子序列 来求解。因为给的字典比较多,最多有1w个,而LCS的算法时间复杂度是O(n*m),n,m分别对应两个字符串的长度。还要乘上字典的个数和所要匹配的单词数,不出意外地。。超时了。
后面就想到了暴力求解,直接枚举所有情况,先判断字符串长度差是否大于1,大于1的话直接进行下一个循环,否则再继续划分。(len对应字典词长度,l对应要查询的词长度)
假设匹配成功,只会有以下三种情况。
1. len==l ,只可能是完美匹配,或是替换一个字母
2. len-1==l,查询的词要添加一个字母
3. len==l-1,查询的词要删去一个字母
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <cmath> 5 using namespace std; 6 char word[10005][20]; 7 char str[20]; 8 int main(){ 9 int cnt=-1; 10 while (gets(word[++cnt])!=NULL && word[cnt][0]!='#'); 11 while (gets(str)!=NULL && str[0]!='#') { 12 vector<int>v; 13 int ok=0; 14 int l=(int)strlen(str); 15 printf("%s",str); 16 for (int i=0; i<cnt; i++) { 17 int len=(int)strlen(word[i]); 18 int cur=0,j=0,k=0; 19 if(fabs(len-l)>1) continue; 20 if(len-l==0){//情况1 21 while (str[j] && word[i][j] && cur<=1) { 22 if (str[j]!=word[i][j]) cur++; 23 j++; 24 } 25 if(cur==0){ 26 ok=1; 27 printf(" is correct\n"); 28 break; 29 } 30 }else if(len-l==1){//情况2 31 while (str[k] && word[i][j]) { 32 if(str[k]!=word[i][j]){ 33 cur++,j++; 34 continue; 35 } 36 j++;k++; 37 } 38 }else if(l-len==1){//情况3 39 while (str[k] && word[i][j]) { 40 if(str[k]!=word[i][j]){ 41 cur++,k++; 42 continue; 43 } 44 j++;k++; 45 } 46 } 47 if(cur<=1) v.push_back(i); 48 49 } 50 if(!ok){ 51 printf(":"); 52 for (int j=0; j<v.size(); j++) { 53 printf(" "); 54 printf("%s",word[v[j]]); 55 } 56 printf("\n"); 57 } 58 } 59 return 0; 60 }
另附上用LCS做的超时版本。。有用LCS过的 欢迎讨论
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <string> 5 #include <cmath> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 char word[10005][20]; 10 char str[20]; 11 int main(){ 12 int cnt=-1; 13 while (gets(word[++cnt])!=NULL && word[cnt][0]!='#'); 14 while (gets(str)!=NULL && str[0]!='#') { 15 vector<int>v; 16 int ok=0; 17 int l=(int)strlen(str); 18 printf("%s",str); 19 for (int i=0; i<cnt; i++) { 20 int lcs[20][20]; 21 int Max=0; 22 int len=(int)strlen(word[i]); 23 if(fabs(len-l)>1) continue; 24 memset(lcs, 0, sizeof(lcs)); 25 for (int j=0; j<len; j++) { 26 for (int k=0; k<l; k++) { 27 if(word[i][j]==str[k]) lcs[j+1][k+1]=lcs[j][k]+1; 28 else lcs[j+1][k+1]=max(lcs[j+1][k], lcs[j][k+1]); 29 Max=max(Max, lcs[j+1][k+1]); 30 } 31 } 32 if(max(len,l)==Max){//完全匹配 33 ok=1; 34 printf(" is correct\n"); 35 break; 36 }else if(max(len,l)==Max+1){//增删改其中的一个情况 37 if(len==Max || l==Max){//增删情况 38 v.push_back(i); 39 }else{ 40 int j=0; 41 int cur=0; 42 while (word[i][j] && str[j]) { 43 if(word[i][j]==str[j]) cur++; 44 j++; 45 } 46 if(cur==Max){//修改一个的情况 47 v.push_back(i); 48 } 49 } 50 } 51 } 52 if(!ok){ 53 printf(":"); 54 for (int j=0; j<v.size(); j++) { 55 printf(" "); 56 printf("%s",word[v[j]]); 57 } 58 printf("\n"); 59 } 60 } 61 return 0; 62 }