leetcode-最长无重复子串

leetcode-最长无重复子串

法一

剑指offer的思路是动态规划。

(1)用一个position数组(128),存放所有字符最后一次出现的位置。

(2)用dp[i]表示以第i个字符结尾的无重复子串的最大长度:

如果第i个字符之前没有出现过,那么dp[i]=dp[i-1]+1

如果第i个字符之前出现过,那么就判断2个字符最近的距离d=i-position[ch]与dp[i-1]的关系

1)d<=dp[i-1];dp[i]=d

2)d>dp[i-1];dp[i]=dp[i-1]+1

(3)遍历dp数组求最值即可。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>

using namespace std;

int getloogestlen(const string &str)
{
    int len=str.size();
    if(len==0)
        return 0;
    int dp[len];
    memset(dp,0,sizeof(dp));

    int position[128];
    for(int i=0;i<128;i++)
    {
        position[i]=-1;
    }

    dp[0]=1;
    position[str[0]-0]=0;
    for(int i=1;i<len;i++)
    {
        int pos=str[i]-0;
        if(pos==-1)
            dp[i]=dp[i-1]+1;
        else   //出现过
        {
            int d=i-position[pos];
            if(d>dp[i-1])
                dp[i]=dp[i-1]+1;
            else
                dp[i]=d;
        }
        position[pos]=i;
    }
    int maxlen=-1;
    for(int i=0;i<len;i++)
    {
        if(maxlen<dp[i])
            maxlen=dp[i];
    }
    return maxlen;
}

int main()
{
    string str;
    cin>>str;
    int len=getloogestlen(str);
    cout<<len;
    return 0;
}

法二

跟动态规划的思路有点像。

(1)用position数组记录字符最后一次出现的位置

(2)用res来记录最长的长度,用left来记录局部无重复子串的起始位置

(3)遍历字符串,如果当前字符和局部起始字符一样,就把边界left加1。如果当前字符出现的位置在left前面,那么left就更新为当前字符出现的位置加1。然后更新res即可

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.size();
        if(len==0)
            return 0;
        int a[128];
        fill(a,a+128,-1);
        int res=0;
        int left=0;
        for(int i=0;i<len;i++)
        {
            if(left==a[s[i]-0])
                left+=1;
            else if(left<a[s[i]-0])
                left=a[s[i]-0]+1;

            res=max(res,i-left+1);
            a[s[i]-0]=i;
        }
        return res;
    }
};