uva-1588-Kickdown

此题虽然不难,但由于自己一开始对题目的理解出现问题,导致后来推倒重写。本题要点在于分别让两个字符串一个动另一个不动,输出此时的匹配长度。最后取2个匹配长度中最短的一个即可。我觉得此题我代码还是过长,有以下几个原因:子函数或许可以用for循环实现。最重要的一点:我一直以来的检测即毁灭的做法(即为了检查常常会改变数组元素作为标记)导致了一些不必要的数组及行为的出现。

#include<iostream>

#include<cstring>
#include<algorithm>
using namespace std;
int isame(char *x, char *y) {//x短
for (int j = 0; j <= strlen(y) - strlen(x); j++) {
int sg = 1;//当前合法
for (int i = 0; x[i]; i++) {
if (x[i] + y[j + i] - 2 * '0' > 3) {
sg = 0; break;
}
}
if (sg) return 1;//合法
}
return 0;
}
int main() {
char s1[12], s2[12], s11[12], s22[12];
while (scanf("%s%s", s1,s2) != EOF) {//前短后长或前后等长
if (strlen(s1) > strlen(s2)) std::swap(s1, s2);
memcpy(s11, s1, sizeof(s1));
memcpy(s22, s2, sizeof(s2));
int lens1 = strlen(s1);//len1 is the shorter one
int lens2 = strlen(s2);
if (isame(s1, s2)) { printf("%d\n", lens1 > lens2 ? lens1 : lens2); continue; }
int len1 = 0,i,len2=0;//长上短下
for (i = 0; i < lens1-1; i++) {
s2[lens1 - i-1] = 0;
if (isame(s1 + i + 1, s2)) break;
}
len1 = i + 1 + lens2;
for (i = 0; i < lens1 - 1; i++) {//短上长下
s11[lens1 - i - 1] = 0;
if (isame(s11, s22 + lens2 - lens1 + i + 1)) break;
}
len2 = i + 1 + lens2;
int len = len1 < len2 ? len1 : len2;
printf("%d\n",len );
}
return 0;

}

以下是网上的代码,我认为写的很好,抓住了问题的关键:重合部分的长度。非常巧妙。

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. char h1[110],h2[110];  
  4. int main()  
  5. {  
  6.     while(scanf("%s%s",h1,h2)!=EOF)  
  7.     {  
  8.         int i,j,t,m,n;  
  9.         int temp,conut1,conut2;  
  10.         i=j=t=0;  
  11.         m=strlen(h1);  
  12.         n=strlen(h2);  
  13.         while(j<m&&i<n)  
  14.         {  
  15.             if(h1[j]+h2[i]-96<=3)  
  16.             {  
  17.                 i++,j++;  
  18.             }  
  19.             else  
  20.                 t++,i=0,j=t;  
  21.         }  
  22.         conut1=m+n-i;  
  23.         i=j=t=0;  
  24.         while(j<n&&i<m)  
  25.         {  
  26.             if(h2[j]+h1[i]-96<=3)  
  27.             {  
  28.                 i++,j++;  
  29.             }  
  30.             else  
  31.                 t++,i=0,j=t;  
  32.         }  
  33.         conut2=m+n-i;  
  34.         printf("%d\n",conut1 < conut2 ? conut1 : conut2 );  
  35.     }  
  36.     return 0;  
  37. }  

以下这个代码更短且更巧妙,但现在看不太明白...

#include<cstdio>
 #include<cstring>
 const int maxn = 100;
 char a[maxn + 1], b[maxn + 1];
 int n1, n2;
 int min(const int &i, const int &j) {
   return i<j ? i : j;
}
 int minLen(char *s1, char *s2, int &n) {// n为s1的长度 
  int sumLen = n1 + n2, minn = min(n1, n2), len = sumLen;
  for (int i = 0; i<n; i++) {
        int ok = 1, fix = min(n - i, minn);//fix的计算是一个难点 
    for (int j = 0; j<fix; j++)
if (s1[i + j] == '2'&&s2[j] == '2') {
            ok = 0; break;
}
       if (ok&&len>sumLen - fix)len = sumLen - fix;
}
   return len;
}
int main() {
     while (scanf("%s%s", &a, &b) == 2) {
         n1 = strlen(a), n2 = strlen(b);//无意中用到了逗号运算符 
minLen(a, b, n1);
minLen(b, a, n2);
        printf("%d\n", min(minLen(a, b, n1), minLen(b, a, n2)));//用min函数取两次结果的最小值 

}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值