3.1 字符串移位包含的问题

    给定两个字符串s1和s2,要求判定s2是否能够被通过s1作循环移位(rotate)得到的字符串包含。例如,给定s1=AABCD和s2=CDAA,返回true;给定s1=ABCD和s2=ACBD,返回false。

    分析与解法

    【解法一】

    从题目中可以看出,我们可以使用最直接的方法对s1进行循环移位,再进行字符串包含的判断,从而遍历其所有的可能性。

    因此,可以用如下的代码实现:

    代码清单3-1

    alt

    如上,穷举s1(如ABCD)做循环移位(rotate)所能得到的所有字符串,看其结果是否与s2相等。若字符串的长度N较大,显然效率很低。

    【解法二】

    我们也可以对循环移位之后的结果进行分析。

    以s1=ABCD为例,先分析对s1进行循环移位之后的结果,如下所示:

    ABCD→BCDA→CDAB→DABC→ABCD…

    假设我们把前面移走的数据进行保留,会发现有如下的规律:

    ABCD→ABCDA→ABCDAB→ABCDABC→ABCDABCD

    因此,可以看出对s1做循环移位(rotate)所得到的字符串都将是字符串s1s1的子字符串。如果s2可以由s1循环移位(rotate)得到,那么s2一定在s1s1上。至此我们将问题转换成考察s2是否在s1s1上,可通过调用一次strstr函数得到结果。

    例如若CDAB在ABCDABCD上可以找到,那么CDAB也可通过ABCD做循环移位得到(ABCD循环左移或循环右移两位)。

    总结

    第二种方法利用了“提高空间复杂度来换取时间复杂度的降低”的思路,适用于对时间复杂度要求高的场合。