Unique Substrings in Wraparound String
问题:
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.
解决:
【题意】
字符串s是小写字母"abcdefghijklmnopqrstuvwxyz"的无限循环,s看起来像这样:"...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd...."
现在我们有另外一个字符串p。你需要寻找p有多少个非空子串在s中出现。输入p,你需要输出s中有多少个不同的p的非空子串。
① 由于封装字符串是26个字符按顺序无限循环组成的,那么满足题意的p的子字符串要么是单一的字符,要么是按字母顺序的子字符串。
我们看abcd这个字符串,以d结尾的子字符串有abcd, bcd, cd, d,那么我们可以发现bcd或者cd这些以d结尾的字符串的子字符串都包含在abcd中,那么我们知道以某个字符结束的最大字符串包含其他以该字符结束的字符串的所有子字符串。那么题目就可以转换为分别求出以每个字符(a-z)为结束字符的最长连续字符串就行了,我们用一个数组count记录下来,最后在求出数组count的所有数字之和就是我们要的结果了。
class Solution { //18ms
public int findSubstringInWraproundString(String p) {
if (p == null || p.length() == 0) return 0;
int[] count = new int[26];//记录以每个字符为结尾的字符串的长度
int len = 0;//记录子串的长度
char[] pchar = p.toCharArray();
for (int i = 0;i < pchar.length;i ++){
if (i > 0 && (pchar[i] == pchar[i - 1] + 1 || pchar[i - 1] - pchar[i] == 25)){
len ++;
}else {
len = 1;
}
count[pchar[i] - 'a'] = Math.max(count[pchar[i] - 'a'],len);
}
int res = 0;
for (int i = 0;i < count.length;i ++){
res += count[i];
}
return res;
}
}
② 进化版
class Solution { //17ms
public int findSubstringInWraproundString(String p) {
if (p == null || p.length() == 0){
return 0;
}
int[] count = new int[26];
int res = 0;
int len = 0;
char[] pchar = p.toCharArray();
for (int i = 0;i < pchar.length;i ++){
int cur = pchar[i] - 'a';
if (i > 0 && pchar[i - 1] != (cur + 26 - 1) % 26 + 'a'){
len = 0;
}
if (++ len > count[cur]){
res += len - count[cur];
count[cur] = len;
}
}
return res;
}
}