当前位置:   article > 正文

[算法] 滑动窗口算法--查找最长子串_滑动窗口中找出最长相同字符串 (searching for longest common strin

滑动窗口中找出最长相同字符串 (searching for longest common string within the

滑动窗口

  滑动窗口也叫尺取法,是一种在字符串或数组中查找满足条件的算法。
  例如可以在字符串中查找满足条件的子串。

滑动窗口图示

  在这里,规定窗口大小为3,每次向右滑动一位。
  当然,窗口的大小可以随意调整,调整至满足条件即可。
在这里插入图片描述

2. 利用滑动窗口查找最长子串

基本原理

思路一:

  规定开始窗口大小为0,利用左右指针指向子串的开始和结束。截取左右指针中的子串,每次移动右边指针将元素加入子串并判断在子串中是否有相同元素,如果有则移动左指针。一直重复上述操作,直到右指针指向字符串尾。记录出现的最长子串。
在这里插入图片描述
代码:

// 判断右指针元素是否在前方出现,没有出现则扩大窗口大小,元素出现则改变左指针位置
// 此方法利用滑动窗口将窗口的字符串截取出来存到子串中,判断子串中是否包含即将加入的字符串,
int lengthOfLongestSubstring(string s) {
    if (s.length() <= 1)
    {
        return s.length();
    }

    int left = 0, right = 0;
    int maxlen = 0;

    while (right <= s.length())
    {
        // 截取子串
        string sub = s.substr(left, right - left);
        maxlen = maxlen > right - left ? maxlen : right - left;
        
        // 判断子串中是否含有新加入的字符,如果含有新加入的字符,改变窗口大小
        while ( left < right && sub.find(s[right]) != string::npos)
        {
            left++;
            // 窗口大小发生改变 截取新串
            sub = s.substr(left, right - left);
        }

        right++;
    }

    return maxlen;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

思路二:

  原理与上述相同,但不用截取子串,效率更高。

int lengthOfLongestSubstring(string s) {
	if (s.length() <= 1)
	{
	    return s.length();
	}

    int left = 0, right = 1, max = 1;

    while (right < len)
    {
        // 在子串中进行查找该字符第一次出现的位置,如果第一次出现的位置与右值相同,则代表没有出现过该字符
        while (right < len && s.find(s[right], left) == right)
        {
            right++;
        }
        max = right - left > max ? right - left : max;
        left++;
    }
    return max;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

思路三:

  与上述思路完全不同,不再利用滑动窗口。出现一个字符记录一个字符,并且累加器累加,如果遇到已经出现过的字符,则根据这个重复字符出现在字符串中的位置,决定累加器的值。重复上述操作,记录最大累加器的值。

int lengthOfLongestSubstring(string s) {
    if (s.length() <= 1)
    {
        return s.length();
    }

    int acsii[256] = { 0 };     // 记录字符串出现的次数
    int count = 0;
    int maxcount = 1;

    for (int i = 0; i < s.length(); i++)
    {
        // 如果字符已经出现
        if (acsii[s[i]] == 1)
        {
            // 判断前后时候是一样的字符串,如果重复,则当前字符为新子串,则让计数器重新计数
            if (s[i] == s[i - 1])
            {
                //如果计数器大于字符串一半长度则说明不会出现更长子串, 所以清零也就没有必要了
                if (count > s.length() / 2)
                {
                    break;
                }
                count = 0;
            }  
            else
            {
                // 如果该串与周边字符串没有关系,则对长度-1,再开始计数,
                count--;  
            }  
        }
       
        // 如果没有字符出现则累加器++,如果有字符出现过则对长度改变后再++
        count++;
        acsii[s[i]] = 1;
        maxcount = maxcount > count ? maxcount : count;
    }

    return maxcount;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/276962
推荐阅读
相关标签
  

闽ICP备14008679号