题目:
Consider the string s
to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s
will look like this: "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....".
Now we have another string p
. Your job is to find out how many unique non-empty substrings of p
are present in s
. In particular, your input is the string p
and you need to output the number of different non-empty substrings of p
in the string s
.
Note: p
consists of only lowercase English letters and the size of p might be over 10000.
Example 1:
Input: "a" Output: 1 Explanation: Only the substring "a" of string "a" is in the string s.
Example 2:
Input: "cac" Output: 2 Explanation: There are two substrings "a", "c" of string "cac" in the string s.
Example 3:
Input: "zab" Output: 6 Explanation: There are six substrings "z", "a", "b", "za", "ab", "zab" of string "zab" in the string s.
Subscribe to see which companies asked this question
class Solution {
public:
int findSubstringInWraproundString(string p) {
int size = p.size(),totalsum=0;
if (size == 0)return 0;
vector<int> count(26,0);
for (int i = 0; i < size-1; i++){
int k = i,cou=1;
while (k<size-1&&(p[k+1] - p[k] == 1 || p[k] - p[k+1] == 25)){//两种特殊情况
k++;
cou++;
}
if (cou>count[p[i] - 'a'])count[p[i] - 'a'] = cou;
}
//处理最后一个元素
if (count[p[size - 1] - 'a'] == 0)count[p[size - 1] - 'a'] = 1;
for (int i = 0; i < 26; i++)totalsum += count[i];
return totalsum;
}
};
运行结果:
Submission Result: Accepted More Details
分析:
这个题的目标串z和a是相连的,即"...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd...."当a的前面是z的时候依然可以看成是连续的子串。在算法实现的时候,最大的问题就是出现类似"abcabcd"的时候,
前面的"abc"会出现的子串有:a,b,c,ab,bc,abc;
后面的“abcd”会出现的子串有:a,b,c,d,ab,bc,cd,abc,bcd,abcd,在应用普通方法进行累加的时候,会出现重复统计,当时第一反应是建立一个hashmap,但是这样空间复杂度很大且还要将每一个出现过的子串添加到hashmap中,实现难度较大;
但是,换个角度思考,在字符串种p中,出现的字母也就是26个,如果我们求得以每个字母开头的子串,然后再将它们加起来,就可以得到所有的子串,比如说:
example: xyzabcefg
longest(x) = 6, ==> we get 6 sub strings started from x, x xy xyz xyza xyzab xyzabc
longest(y) = 5 ==> y yz yza yzab yzabc
longest(c) = longest(g) = 1 ==> c, g
这样问题就可以变得简单了。此时就是如何求得longest(a)。对于上述的"abcabcd"我们可以求得两个以a为开头的所有子串的长度分别是6和10,这时我们会取较大值,因为只要是连续出现的以a为开头的字符串的形式一定是"abcd...xyzabc..."所以长度长的串一定包含长度短的所有子串,就像abcd的子串包含abc的所有子串一样。。。
以下是另一种更简洁的方法:
class Solution{
public:
int findSubstringInWraproundString(string p) {
vector<int> letters(26, 0);
int res = 0, len = 0;
for (int i = 0; i < p.size(); i++) {
int cur = p[i] - 'a';
if (i > 0 && p[i - 1] != (cur + 26 - 1) % 26 + 'a') len = 0;
if (++len > letters[cur]) {
res += len - letters[cur];
letters[cur] = len;
}
}
return res;
}
};