1.8 Assume you have a method isSubstring which checks if one word is a substring of another. Given two strings, s1 and s2, write code to check if s2 is a rotation of s1 using only one call to isSubstring (i.e., “waterbottle” is a rotation of “erbottlewat”).
译文:假定你有一个isSubstring函数,可以判断是否一个字符串是另一字符串的字串。给定s1和s2两个字符串,写一个程序只需调用一次isSubstring函数就可以检查是否s2是s1的旋转字符串。示例:"waterbottle"是"erbottlewat"的旋转字符串。
这个题目比较特殊的是你需要调用它给定的一个功能函数isSubstring。而不能直接从字符串s1和s2出发,因为二者并存在子字符串的关系。有另一个思路那就是,不断的旋转s1,然后不断地调用isSubstring来判断是否s1与s2相等,但这违反了题给的条件,只能另辟他路。我们得充分利用给定的isSubstring这个函数的功能,即判定字串关系。旋转字符串就是将字符串循环移位多少位,那就将字符串首尾相连,那么它的旋转字符串肯定在这个环里面,多了个环比较麻烦,且似乎不好利用subString这个函数,我们可以将这个字符串自加,即s1+s1,这样实际也具备环的特点,并且处理起来更加方便。
s1 + s1 = waterbottlewaterbottle;很明显s1的所有旋转字符串均是s1+s2的字串,这样的话,处理起来就轻松多了。代码如下
bool isRotation(string s1, string s2) { int len = s1.length(); if ((s2.length == len) && (len > 0)) { return isSubstring(s1 + s1, s2); } return false; }
针对旋转字符串和字串也是经常出现的问题,我们这里也稍稍讨论一下。
旋转字符串:偶然间在《编程珠玑》上看到一个关于旋转字符串的题目,具体记不清了,大致是给定一个字符串str,要求得到旋转 i 个位置后的字符串。eg:str = "abcdefg",i = 3,那么得到的字符串为 str = "defgabc"。
这里介绍的是一种采用递归的方法,先翻转前面 i 个字符,然后翻转 i 位置后面的字符,最后再将整个字符串翻转一次,就得到结果了。这个方法很巧妙,不是我想出来的。翻转字符串前面的文章中有讲过,这里就搬过来还需要修改一下,代码如下
void swap(char &a, char &b) { if (a != b) { a ^= b; b ^= a; a ^= b; } } void reverse(string &str, int start, int end) //字符串中的指定部分start--end翻转 { while (start < end) swap(str[start++], str[end--]); }那么我们实现的时候就三次调用该翻转函数
reverse(str, 0, i-1); reverse(str, i, len - 1); reverse(str, 0, len - 1);最后得到结果。
子串:估计就会想到kmp字符串匹配算法了,这个算法很巧妙,这里就不花篇幅来讲解了,大家感兴趣就可以参考其余资料