这个问题很笼统,但我将举一个具体的例子。
解释了需要解决的具体问题here。描述很长,所以我不会剪切和粘贴,但基本思路是输入字符串S和T(因为它们在下面的代码中调用),找到需要对S生成T的最小更改次数。一个变化可能是:
以下是我要跟踪的解决方案。我正在寻找的是如何最好地解决方案的提示。我可以使用哪些方法来阅读和理解代码(让我们放弃逐步调试代码)。
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
char S[2010];
char T[2010];
int lens,lent;
int main()
{
int i,j,ma,p;
while(scanf("%s%s",S,T)!=EOF)
{
lens=strlen(S);
lent=strlen(T);
ma=0;p=0;
for(i=0;i<lens;i++)
{
p=0;
for(j=0;j<lent;j++)
{
if(i+j>=lens)
break;
if(S[i+j]==T[j]){p++;}
}
if(ma<p)
ma=p;
if(ma==lent)
break;
}
for(i=0;i<lent;i++)
{
p=0;
for(j=0;j<lens;j++)
{
if(i+j>=lent)
break;
if(T[i+j]==S[j]){p++;}
}
if(ma<p)
ma=p;
if(ma==lent)
break;
}
printf("%d\n",lent-ma);
}
return 0;
}
答案 0 :(得分:3)
第1步:向自己解释变量代表什么:
S
:我们想要从中提取子字符串的字符串
T
:在用尽可能少的操作修改提取的子字符串之后,我们想要实现的字符串
lens
:字符串S的长度
lent
:字符串T的长度
i
:S中从中提取子字符串的索引
j
:字符串T中我们想要与子字符串中相应字符匹配的字符中的索引
p
:为当前调查的子字符串
ma
:任何子字符串的最大匹配字符数
第2步:确定了这些含义后,将第一个循环翻译成单词非常简单:
for loop 1 : selects a start position of the substring
set the match counter to 0, since we start investigation of a new substring
for loop 2 : loops through the substring
if 1 : if there is no char left to read string S, stop looping
if 2 : if the current character in the extracted substring matches
a character in the "goal" string, increment the match counter (p)
if 3 : now, we finished looping through a substring,
if the count of matching characters in the substring and the goal
string was higher than for any of the previous counts,
then store this value as the max count
if 4 : if the max count of matching characters is equal to the
length of the "goal string", dr Moriatry can receive the goal string
with 0 substring changes, and hence, we can stop looping
下一个循环类似。 S和T的作用有所逆转。但请注意,S和T的角色尚未完全逆转(正如有些人所说)。外部for循环的结束条件在两种情况下都使用T的长度,这是有道理的。
这里我们从字符串T(“目标”字符串)中提取子字符串,并尝试将它们与字符串S匹配。为什么我们这样做?
我希望编写代码的人想要考虑以下情况,例如:
S = "b" T = "abc"
如果我们只从S中提取子串并将它们与整个T字符串匹配,从第一个索引开始(就像第一个循环那样),我们只比较“做b
(在S中)匹配a
(T中的第一个字符)然后我们继续说:“由于没有子字符串匹配,我们需要3个字符串更改操作来接收字符串T”(这显然是错误的,因为我们可以实现它通过选择“b”作为要提取的子字符串,并进行2次更改操作以最终得到T)
答案 1 :(得分:2)
最好的解决方案是在理解代码时重写代码。几件事:
foo()
foo(S,T)
和foo(T,S)
答案 2 :(得分:2)
理解代码的关键是理解变化最小的变量的含义,在本例中为ma和p,并识别编码习语。
两个代码段
if(ma<p)
ma=p;
if(ma==lent)
break;
是变量p的“高水位线”成语(在最大可能值上具有中断条件)。只要在从i开始的LHS子串的j位置处的字符与RHS的j位置字符匹配,p就递增。因此,对于由j(内部循环)索引的循环,p是处于相同j位置的相同字符的数量。所以我会将p(至少在我脑中)重命名为“number_of_identical_chars_in_same_pos”。
由i索引的循环找到LHS中每个子字符串的最高p(保存在ma中),该子字符串以LHS的最后一个字符结尾(如果子字符串长,则更早)。所以ma应该重命名为“max_common_chars_in_a_span”。这两个循环一起找到任意子串的相同位置中的最大公共字符数,以任何一方的最后一个字符结尾。
最后一步(留给认真的学生)是要了解这是如何解决问题的,这是数学,而不是编程。
答案 3 :(得分:1)
我首先要对程序进行一些字符串操作。第一步是尝试为变量提供更好的名称。
我用sPos替换'i'作为字符串S中的位置。好吧,至少这适用于第一个循环,对于第二个循环'i'改变意思是T中的位置,所以我想实际上然后决定摆脱i,而是有两个变量,所以每个变量都有一个与其名称相匹配的目的。
然后对j,ma和p尝试相同的事情。
一旦完成,我会考虑尝试找出两个'for'循环的作用。他们看起来几乎相同。也许它们可以分成一个被调用两次的函数。再次,尝试弄清楚这个函数的作用并仔细命名,以便名称解释其用途。
重复这样的步骤,直到你得到一些让人有意义的代码。
答案 4 :(得分:1)
ma
)。