题目描述:
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.
(意思就是找字符串p中在循环字符串s"abcd...hyzabcd...hyzabc..."中的子集)
思路:一开始想的是用一个和字符串p一样长的数组count,用count[i]保存到达i元素时的长度大于两个以上子串,用set来保存单个字符的子集,两个相加便是总子集数
public class Unique_Substrings_in_Wraparound_Strin {
public static int findSubstringInWraproundString(String p)
{
if(p.length()==0)
{
return 0;
}
//记录到达该点之前的子串数
int count[] = new int[p.length()];
//卡一个范围从可以连起来到链子结束
int flag = 0;
//set和al都要可以去重,set去单个字母的重,al去的是组合的重
Set set = new HashSet();
ArrayList<String> al = new ArrayList<String>();
//每个单个字母一定在字符串s中所以每个不重复的字母都算一个
for(int i=0;i<p.length();i++)
{
set.add(p.charAt(i));
}
for(int i=1;i<p.length();i++)
{
//无论是能不能跟前面连上都要将前一个值拿过来,如果可以连上再算比原来多出来的
count[i] += count[i-1];
if(p.charAt(i)-p.charAt(i-1)==1||p.charAt(i)-p.charAt(i-1)==-25)
{
//当i元素可以和前一个元素所在的链子连上时,其增加的子集数目便是i元素到该条链子开端的长度(列举就可得)
for(int j=flag;j<i;j++)
{
if(!al.contains(p.substring(j,i+1)))
{
al.add(p.substring(j,i+1));
count[i]++;
}
}
}
else
{
flag = i;
}
System.out.println(count[i]);
}
return count[p.length()-1]+set.size();
}
public static void main(String[] args)
{
String p = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
System.out.println(findSubstringInWraproundString(p));
}
}
但是这种方法时间复杂度是平方级的,在测试到最后一个测试用例时会被OJ判定超时。
后来看别人的解法,他们将DP数组换为了以26个字母结尾的字符串的数量,举个例子,我们看abcd这个字符串,以d结尾的子字符串有abcd, bcd, cd, d,那么我们可以发现bcd或者cd这些以d结尾的字符串的子字符串都包含在abcd中,而abcd的子串数目则是由以a开头的最大字串长度,以b开头的最大字串长度,以c开头的最大字串长度,以d开头的最大字串长度的和构成,那么我们知道以某个字符结束的最大字符串包含其他以该字符结束的字符串的所有子字符串。
public class Unique_Substrings_in_Wraparound_String低时间复杂度 {
public static int findSubstringInWraproundString(String p)
{
if(p.length()==0)
{
return 0;
}
int result = 0;
//以26个字母结尾的子串数
int count[] = new int[26];
//以某字母结尾的链子的长度就是这条链子上所有以该字母结尾的子串的和
int length = 0;
for(int i=0;i<p.length();i++)
{
if(i!=0&&(p.charAt(i)-p.charAt(i-1)==1||p.charAt(i)-p.charAt(i-1)==-25))
{
length++;
}
else
{
length = 1;
}
count[p.charAt(i)-'a'] = Math.max(count[p.charAt(i)-'a'],length);
}
for(int i=0;i<count.length;i++)
{
result += count[i];
}
return result;
}
public static void main(String[] args) {
String p = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
String s = "abcdzacefg";
System.out.println(findSubstringInWraproundString(p));
}
}