📜  C++ 程序在不重复字符的情况下查找最长子串的长度

📅  最后修改于: 2022-05-13 01:57:06.575000             🧑  作者: Mango

C++ 程序在不重复字符的情况下查找最长子串的长度

给定一个字符串str ,找出不重复字符的最长子字符串的长度。

  • 对于“ABDEFGABEF”,最长的子串是“BDEFGA”和“DEFGAB”,长度为6。
  • 对于“BBBB”,最长的子串是“B”,长度为 1。
  • 对于“GEEKSFORGEEKS”,下图中显示了两个最长的子串,长度为 7

所需的时间复杂度为 O(n),其中 n 是字符串的长度。

方法1(简单:O(n 3 )) :我们可以一一考虑所有子字符串,并检查每个子字符串是否包含所有唯一字符。将有 n*(n+1)/2 个子串。一个子串是否包含所有唯一字符,可以通过从左到右扫描它并保持一个已访问字符的映射在线性时间内检查。该解决方案的时间复杂度为 O(n^3)。

C++
// C++ program to find the length of the longest substring
// without repeating characters
#include 
using namespace std;
  
// This functionr eturns true if all characters in str[i..j]
// are distinct, otherwise returns false
bool areDistinct(string str, int i, int j)
{
  
    // Note : Default values in visited are false
    vector visited(26);
  
    for (int k = i; k <= j; k++) {
        if (visited[str[k] - 'a'] == true)
            return false;
        visited[str[k] - 'a'] = true;
    }
    return true;
}
  
// Returns length of the longest substring
// with all distinct characters.
int longestUniqueSubsttr(string str)
{
    int n = str.size();
    int res = 0; // result
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++)
            if (areDistinct(str, i, j))
                res = max(res, j - i + 1);
    return res;
}
  
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}


C++
// C++ program to find the length of the longest substring
// without repeating characters
#include 
using namespace std;
  
int longestUniqueSubsttr(string str)
{
    int n = str.size();
    int res = 0; // result
  
    for (int i = 0; i < n; i++) {
          
        // Note : Default values in visited are false
        vector visited(256);   
  
        for (int j = i; j < n; j++) {
  
            // If current character is visited
            // Break the loop
            if (visited[str[j]] == true)
                break;
  
            // Else update the result if
            // this window is larger, and mark
            // current character as visited.
            else {
                res = max(res, j - i + 1);
                visited[str[j]] = true;
            }
        }
  
        // Remove the first character of previous
        // window
        visited[str[i]] = false;
    }
    return res;
}
  
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}


C++
// C++ program to find the length of the longest substring
// without repeating characters
#include 
using namespace std;
#define NO_OF_CHARS 256
  
int longestUniqueSubsttr(string str)
{
    int n = str.size();
  
    int res = 0; // result
  
    // last index of all characters is initialized
    // as -1
    vector lastIndex(NO_OF_CHARS, -1);
  
    // Initialize start of current window
    int i = 0;
  
    // Move end of current window
    for (int j = 0; j < n; j++) {
  
        // Find the last index of str[j]
        // Update i (starting index of current window)
        // as maximum of current value of i and last
        // index plus 1
        i = max(i, lastIndex[str[j]] + 1);
  
        // Update result if we get a larger window
        res = max(res, j - i + 1);
  
        // Update last index of j.
        lastIndex[str[j]] = j;
    }
    return res;
}
  
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}


C++
#include 
using namespace std;
  
int longestUniqueSubsttr(string s)
{
      
    // Creating a set to store the last positions 
    // of occurrence
    map seen ;
    int maximum_length = 0;
  
    // Starting the initial point of window to index 0
    int start = 0;
  
    for(int end = 0; end < s.length(); end++) 
    {
          
        // Checking if we have already seen the element or
        // not
        if (seen.find(s[end]) != seen.end())
        {
              
            // If we have seen the number, move the start
            // pointer to position after the last occurrence
            start = max(start, seen[s[end]] + 1);
        }
  
        // Updating the last seen value of the character
        seen[s[end]] = end;
        maximum_length = max(maximum_length, 
                             end - start + 1);
    }
    return maximum_length;
}
  
// Driver code
int main()
{
    string s = "geeksforgeeks";
    cout << "The input String is " << s << endl;
    int length = longestUniqueSubsttr(s);
      
    cout<<"The length of the longest non-repeating character "
        <<"substring is "
        << length;
}
  
// This code is contributed by ukasp


输出
The input string is geeksforgeeks
The length of the longest non-repeating character substring is 7

方法2(更好:O(n 2 ))这个想法是使用窗口滑动。每当我们看到重复时,我们都会删除前一次出现并滑动窗口。

C++

// C++ program to find the length of the longest substring
// without repeating characters
#include 
using namespace std;
  
int longestUniqueSubsttr(string str)
{
    int n = str.size();
    int res = 0; // result
  
    for (int i = 0; i < n; i++) {
          
        // Note : Default values in visited are false
        vector visited(256);   
  
        for (int j = i; j < n; j++) {
  
            // If current character is visited
            // Break the loop
            if (visited[str[j]] == true)
                break;
  
            // Else update the result if
            // this window is larger, and mark
            // current character as visited.
            else {
                res = max(res, j - i + 1);
                visited[str[j]] = true;
            }
        }
  
        // Remove the first character of previous
        // window
        visited[str[i]] = false;
    }
    return res;
}
  
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}
输出
The input string is geeksforgeeks
The length of the longest non-repeating character substring is 7

方法4(线性时间) :现在让我们谈谈线性时间解决方案。此解决方案使用额外空间来存储已访问字符的最后索引。这个想法是从左到右扫描字符串,跟踪迄今为止在res中看到的最大长度非重复字符子字符串。当我们遍历字符串时,要知道当前窗口的长度,我们需要两个索引。
1)结束索引( j ):我们将当前索引视为结束索引。
2)起始索引( i ):如果当前字符不存在于前一个窗口中,则与前一个窗口相同。为了检查当前字符是否出现在前一个窗口中,我们将每个字符的最后一个索引存储在数组lasIndex[]中。如果 lastIndex[str[j]] + 1 大于先前的开始,那么我们更新了开始索引 i。否则我们保持相同的 i。

以下是上述方法的实现:

C++

// C++ program to find the length of the longest substring
// without repeating characters
#include 
using namespace std;
#define NO_OF_CHARS 256
  
int longestUniqueSubsttr(string str)
{
    int n = str.size();
  
    int res = 0; // result
  
    // last index of all characters is initialized
    // as -1
    vector lastIndex(NO_OF_CHARS, -1);
  
    // Initialize start of current window
    int i = 0;
  
    // Move end of current window
    for (int j = 0; j < n; j++) {
  
        // Find the last index of str[j]
        // Update i (starting index of current window)
        // as maximum of current value of i and last
        // index plus 1
        i = max(i, lastIndex[str[j]] + 1);
  
        // Update result if we get a larger window
        res = max(res, j - i + 1);
  
        // Update last index of j.
        lastIndex[str[j]] = j;
    }
    return res;
}
  
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}
输出
The input string is geeksforgeeks
The length of the longest non-repeating character substring is 7

时间复杂度: O(n + d),其中 n 是输入字符串的长度,d 是输入字符串字母表中的字符数。例如,如果字符串由小写英文字符组成,则 d 的值为 26。
辅助空间: O(d)

替代实施:

C++

#include 
using namespace std;
  
int longestUniqueSubsttr(string s)
{
      
    // Creating a set to store the last positions 
    // of occurrence
    map seen ;
    int maximum_length = 0;
  
    // Starting the initial point of window to index 0
    int start = 0;
  
    for(int end = 0; end < s.length(); end++) 
    {
          
        // Checking if we have already seen the element or
        // not
        if (seen.find(s[end]) != seen.end())
        {
              
            // If we have seen the number, move the start
            // pointer to position after the last occurrence
            start = max(start, seen[s[end]] + 1);
        }
  
        // Updating the last seen value of the character
        seen[s[end]] = end;
        maximum_length = max(maximum_length, 
                             end - start + 1);
    }
    return maximum_length;
}
  
// Driver code
int main()
{
    string s = "geeksforgeeks";
    cout << "The input String is " << s << endl;
    int length = longestUniqueSubsttr(s);
      
    cout<<"The length of the longest non-repeating character "
        <<"substring is "
        << length;
}
  
// This code is contributed by ukasp
输出
The input String is geeksforgeeks
The length of the longest non-repeating character substring is 7

作为练习,尝试上述问题的修改版本,您还需要打印最大长度 NRCS(上述程序只打印它的长度)。

有关详细信息,请参阅有关最长子串长度的完整文章,而不重复字符!