Problem:Longest Substring Without Repeating Characters
Quesiton
- Given a string, find the length of the longest substring without repeating characters.
Examples:
Given “abcabcbb”, the answer is “abc”, which the length is 3.
Given “bbbbb”, the answer is “b”, with the length of 1.
Given “pwwkew”, the answer is “wke”, with the length of 3.
Note that the answer must be a substring, “pwke” is a subsequence and not a substring.
思路
给定一个字符串,找出这个字符串中最长的无重复子串
判断重复的问题一般都会想到hash,从字符串开始,遍历所有的子串,然后找出最长的不重复子串。利用hash来查重。
基本方法:建立一个hash表visit[200],在子串当中遇到每个字母,标志已经遇到过这个字母。
string str = "abc"
visit['a'] = 1;
但是仔细想想,这个方法要遍历所有的子串,假设字符串长度为n,时间复杂度就是O(n^2),如果字符串的长度有好几万,那这个方法就吃不消了。
通过观察发现,对于当前元素,寻找最长不重复子串,要么就是与前面的最长不重复子串构成新的子串,要么就是与前面稍短一点的子串构成新的子串。假定已经存在一个不重复子串,对于当前字符:
- 如果这个字母不与前面的子串重复,那么就可以以它为结尾,构成一个新的不重复子串。这个字符的不重复子串长度 = 前面的不重复子串 + 1。
比如abcd,abc是一个不重复子串,在d这个字母上,最长不重复子串为abcd - 如果这个字母在前面的子串里,而且这个重复的下标在最长不重复子串起始位置之后,则这个位置的不重复子串长度 = 当前字母的下标 - 前面重复的字母的下标, 新的子串是从前面重复的字母的下标之后开始
比如abca, abc是一个不重复子串,s[3] = ‘a’ 这里,不重复子串应该为”bca”,长度等于 3 - 0 = 3 - 实际上这种思路就是Dynamic Programming,将在整个字符串中找最长不重复子串的问题分解一下,找到不同状态、过程之间的联系,然后寻求一种递推关系,简化求解。在这里就是找到不同子串之间存在的联系,然后降低解决问题的复杂度。
- 就像Wiki所说
Dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems.
解题代码
#include <iostream>
#include <memory.h>
#include <string>
using namespace std;
class Solution{
public:
int lengthOfLongestSubstring(string s) {
int length = 0, last_start = 0,
dp[50000]= {0}, visit[256];
memset(visit, -1, sizeof(visit));
visit[s[0]] = 0;
dp[0] = 1;
for(int i = 1; i < s.size(); i++) {
dp[i] = (visit[s[i]] != -1 && last_start <= visit[s[i]]) ? i-visit[s[i]] : dp[i-1]+1;
last_start = (visit[s[i]] != -1 && last_start <= visit[s[i]]) ? visit[s[i]] : last_start;
visit[s[i]] = i;
length = (dp[i] > length ? dp[i] : length);
}
if (s.size() == 1) length = 1;
return length;
}
};