我觉得这是一个很好的挑战。这个练习真正迫使我们在语言和算法的非常低的层面上思考。没有lambda、没有stream、没有regex、没有find、没有substring,什么都没有。只有旧的CharAt、一些for循环等等。本质上,我制作了一个查找方法,该方法查找要查找的字符串的第一个字符,然后进行另一个查找,从那一点开始考虑您的规则。如果失败,它会回到找到的第一个索引,加1,直到字符串的末尾为止,执行多少次迭代。如果没有找到匹配项,则应返回false。如果只找到一个,则足以将其视为子字符串。最重要的边角情况在计算开始时考虑,以便如果检测到假定为某个确定的东西,它就不会继续进行。因此,'*'单独表示任何字符匹配,我们可以用\来转义它。我试图包括大多数边角情况,这确实是一个挑战。我不完全确定我的代码是否涵盖了您的所有情况,但它应该涵盖相当多的情况。我真的想帮助您,所以这是我的方法,这是我的代码:
package com.jesperancinha.string;
public class StringExercise {
private static final char ASTERISK = '*';
private static final char BACKSLASH = '\\';
public boolean checkIsSubString(String mainString, String checkString) {
int nextIndex = getNextIndex(0, checkString.charAt(0), mainString);
if (nextIndex == -1) {
return false;
}
boolean result = checkFromIndex(nextIndex, mainString, checkString);
while (nextIndex < mainString.length() - 1 && nextIndex > -1) {
if (!result) {
nextIndex = getNextIndex(nextIndex + 1, checkString.charAt(0), mainString);
if (nextIndex > -1) {
result = checkFromIndex(nextIndex, mainString, checkString);
}
} else {
return result;
}
}
return result;
}
private int getNextIndex(int start, char charAt, String mainString) {
if (charAt == ASTERISK || charAt == BACKSLASH) {
return start;
}
for (int i = start; i < mainString.length(); i++) {
if (mainString.charAt(i) == charAt) {
return i;
}
}
return -1;
}
private boolean checkFromIndex(int nextIndex, String mainString, String checkString) {
for (int i = 0, j = 0; i < checkString.length(); i++, j++) {
if (i < (checkString.length() - 2) && checkString.charAt(i) == BACKSLASH
&& checkString.charAt(i + 1) == ASTERISK) {
i++;
if (mainString.charAt(j + nextIndex) == BACKSLASH) {
j++;
}
if (checkString.charAt(i) != mainString.charAt(j + nextIndex)) {
return false;
}
}
if (i > 0 && checkString.charAt(i - 1) != BACKSLASH
&& checkString.charAt(i) == ASTERISK) {
if (i < checkString.length() - 1 && (j + nextIndex) < (mainString.length() - 1)
&& checkString.charAt(i + 1) !=
mainString.charAt(j + nextIndex + 1)) {
i--;
} else {
if (j + nextIndex == mainString.length() - 1
&& checkString.charAt(checkString.length() - 1) != ASTERISK
&& checkString.charAt(checkString.length() - 2) != BACKSLASH) {
return false;
}
}
} else {
if ((j + nextIndex) < (mainString.length() - 2) &&
mainString.charAt(j + nextIndex)
!= checkString.charAt(i)) {
return false;
}
}
}
return true;
}
}
我已经编写了一组单元测试,但如果我在这里放置整个类,它会太长,而我想要展示的只是我在单元测试中实现的测试用例。以下是我为此案例编写的单元测试的精简版本:
package com.jesperancinha.string;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
class StringExerciseMegaTest {
@Test
void checkIsSubString() {
StringExercise stringExercise = new StringExercise();
boolean test = stringExercise.checkIsSubString("abcd", "a*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("abcd", "a\\*c");
assertThat(test).isFalse();
test = stringExercise.checkIsSubString("a*c", "a\\*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdsadasa*c", "a\\*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdsadasa*csdfdsfdsfdsf", "a\\*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdsadasa**csdfdsfdsfdsf", "a\\*c");
assertThat(test).isFalse();
test = stringExercise.checkIsSubString("aasdsadasa**csdfdsfdsfdsf", "a*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdsadasa*csdfdsfdsfdsf", "a*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdweriouiauoisdf9977675tyhfgh", "a*c");
assertThat(test).isFalse();
test = stringExercise.checkIsSubString("aasdweriouiauoisdf9977675tyhfgh", "dwer");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdweriouiauoisdf9977675tyhfgh", "75tyhfgh");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdweriou\\iauoisdf9977675tyhfgh", "riou\\iauois");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdweriou\\*iauoisdf9977675tyhfgh", "riou\\\\*iauois");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdweriou\\*iauoisdf9\\*977675tyhfgh", "\\\\*977675tyhfgh");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("aasdweriou\\*iauoisdf9\\*977675tyhfgh", "\\*977675tyhfgh");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("\\*aasdweriou\\*iauoisdf9\\*977675tyhfgh", "\\*aasdwer");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("*aasdweriou\\*iauoisdf9\\*977675tyhfgh", "*aasdwer");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("abcd", "bc");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("abcd", "zbc");
assertThat(test).isFalse();
test = stringExercise.checkIsSubString("abcd", "*bc*");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("*bcd", "\\*bc*");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("abcd", "a*c");
assertThat(test).isTrue();
test = stringExercise.checkIsSubString("abcd", "az*bc");
assertThat(test).isFalse();
}
}
\\*
的意思是反斜杠(第一个)后面跟着一个字面上的星号。 - Henry