【死磕算法·字符串问题】最长无重复子串问题

题目大意:
给定一个字符串str,求该字符串中的最长无重复子串的长度。

如“abcd”的最长无重复子串是“abcd”,长度为4;“abcb”的最长无重复子串是“abc”,长度为3。

题目思路:

遍历字符串,表示出以每个字符串元素str[i]为结尾的最长无重复子串长度,遍历完成后求最大值即可。

如何求以str[i]为结尾的最长无重复子串长度呢?

1、得到以str[i-1]为结尾的最长无重复子串长度pre,获取对应最长无重复子串的起始索引值,记为lastleft;

2、通过map[str[i]] 得到当前元素上一次出现的位置(即位置在当前元素左边的重复元素),取该位置索引值加1,记为nowleft。

如果nowleft>lastleft,当前元素的最大无重复子串的起始位置只能取nowleft,不然再往左取一位就会取到该元素的重复值。

如果nowleft<lastleft,当前元素的最大无重复子串的起始位置只能取lastleft,不然再往左取一位就会取到该元素前一位元素的重复值。

总结出来,当前元素的最大无重复子串的起始位置取得是nowleft和lastleft的最大值。

3、更新以当前元素为结尾的最大无重复子串长度pre,以及当前元素最近一次的出现位置map[str[i]]为当前位置。

遍历字符串str的同时维护一个map数组和pre变量,其中:
map数组:数组各值初始化为-1,mymap[i]存储str[i]在字符串中上一次出现的位置.

pre变量表示以str[i-1]为结尾的最大无重复子串长度。

如果nowleft<lastleft:

如果nowleft>lastleft:

nowleft 和lastleft相等时,取任意一个即可。

代码实现:
 

class DistinctSubstring {
public:
    int longestSubstring(string A, int n) {
        // write code here
        int mymap[300];//表示当前元素上一次出现的index,如果之前没出现过就没有这个关键词;
        int pre = 0,index = 0;//index 表示以当前元素为结尾的最长无重复子序列的起始位置。
        int maxnum = 0;
        memset(mymap,-1,sizeof(mymap));
        for(int i = 0;i<n;i++){
            if(mymap[A[i]]!=-1)//之前出现过该元素
            {
            int lastleft = i-pre;
            int nowleft = mymap[A[i]]+1;
               index = nowleft;
             if(lastleft>nowleft)
               index = lastleft;
             mymap[A[i]] = i;
             pre = i-index+1;
            }
            else{
                  mymap[A[i]] = i;//记录下来
                  pre++;
            }
            if(pre>maxnum)
                maxnum = pre;
           
        }
        return maxnum;
    }
};

注意点:str[i] 对应着ascii码,因此可以直接作为map的索引值。

猜你喜欢

转载自blog.csdn.net/gulaixiangjuejue/article/details/85028228