题目描述
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含’a’~'z’的字符。
例如,在字符串“arabcacfr”中,最长的不含重复字符的子字符串是“acfr”,长度是4.
实现
- 方法:动态规划
- 预备:
– 字符串“arabcacfr”,显然 f ( 0 ) = 1 f(0)=1 f(0)=1
–定义函数: f ( i ) f(i) f(i) 表示以第 i i i个字符为结尾的不包含重复字符的子字符串的最长长度, f ( i − 1 ) f(i-1) f(i−1)已知 - 思路:
1、 第 i i i个字符没出现过, f ( i ) = f ( i − 1 ) + 1 f(i)=f(i-1)+1 f(i)=f(i−1)+1
计算f(1):r没出现过,f(1)=f(0)+1=2,目前最长不重复 ar
2、 第 i i i个字符出现过,计算第 i i i个字符和上次出现的位置的距离 d d d
① d ≤ f ( i − 1 ) d≤f(i-1) d≤f(i−1)
----第i个字符串上次出现在f(i-1)对应的最长字符串之中,因此f(i)=d
----如,计算f(2),a字符,d=2即a出现在f(1)对应的最长不含重复字符的子字符串ar中,此时f(2)=d,即f(2)=2,对应ra(rar变为ra)
② d > f ( i − 1 ) d>f(i-1) d>f(i−1)
----第i个字符串上次出现在f(i-1)对应的最长字符串之前,因此仍有 f(i)=f(i-1)+1
----如,计算f(8),r字符,它前一个f字符结尾的f(7)=3,对应acf;r在下标1出现过,d=7,>f(7),说明r不在f(7)对应的最长不含重复自字符串acf中,把r拼接到acf不会出现重复,f(8)=f(7)+1=4,对应acfr
public class C48_string_LongestSubstring {
static int getLongestSubstr(String str) {
int curLen = 0;
int maxLen = 0;
int[] strArr = new int[26];
for (int i = 0; i < 26; i++) {
strArr[i] = -1;
}
for (int i = 0; i < str.length(); i++) {
int preIndex = strArr[str.charAt(i) - 'a'];
if (preIndex < 0 || i - preIndex > curLen) { //没出现过或者d>f(i-1)
curLen++;//f(i)=f(i-1)+1
} else {//d<=f(i-1)
if (curLen > maxLen) {
maxLen = curLen;//保存较大字符串个数
}
curLen = i - preIndex;// f(i)=d
}
strArr[str.charAt(i) - 'a'] = i;//赋值下标位置
}
if (curLen > maxLen) {
maxLen = curLen;
}
return maxLen;
}
}
Test
public static void main(String[] args) {
String str = "arabcacfr";
System.out.println(getLongestSubstr(str));
}