Hướng dẫn giải của Xâu không lặp dài nhất

Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Thuật toán 1: Duyệt 2 for kèm mảng đánh dấu kí tự đã dùng chưa cho mỗi lần duyệt

#include <bits/stdc++.h> 
using namespace std;

int main() {
    // Đọc và ghi file bằng freopen 
    // freopen("ROBOTCHAR.INP", "r", stdin);  
    // freopen("ROBOTCHAR.OUT", "w", stdout); 

    string s;
    cin >> s; // Nhập một chuỗi ký tự từ bàn phím

    int maxLen = 0;            // Biến lưu độ dài lớn nhất của chuỗi con không lặp ký tự
    int n = s.length();        // Độ dài chuỗi đầu vào

    // Duyệt qua từng vị trí i trong chuỗi để bắt đầu một chuỗi con
    for (int i = 0; i < n; i++) 
    {
        vector<bool> visited(26, false); // Mảng đánh dấu 26 chữ cái A-Z đã xuất hiện hay chưa
        int d = 0; // Biến đếm số ký tự khác nhau trong chuỗi con bắt đầu từ vị trí i

        // Duyệt từ vị trí i đến hết chuỗi

        for (int j = i; j < n; j++) 
        {
            if (!visited[s[j] - 'A']) // Nếu ký tự s[j] chưa xuất hiện
            {
                visited[s[j] - 'A'] = true; // Đánh dấu là đã xuất hiện
                d++;                        // Tăng số lượng ký tự khác nhau
                maxLen = max(maxLen, d);   // Cập nhật độ dài lớn nhất nếu cần
            } 
            else break; // Nếu gặp ký tự đã xuất hiện, dừng chuỗi con tại đây

        }
    }


    cout << maxLen << endl;

    return 0;
}

Thuật toán 2 : Sử dụng ý tưởng thuật toán 2 con trỏ để kiểm tra trong cửa sổ đang xét có tồn tại ký tự đang xét chưa?

📌 2. Ý tưởng cụ thể thuật toán: Sliding Window

Sliding Window (cửa sổ trượt) là một kỹ thuật dùng 2 con trỏ (left, right) để quét qua các đoạn con của chuỗi.

  • left: bắt đầu của cửa sổ (vị trí đầu của đoạn con đang xét).
  • right: kết thúc của cửa sổ (vị trí hiện tại đang duyệt tới).
  • Duy trì cửa sổ sao cho tất cả ký tự trong đó là **không lặp.
#include <bits/stdc++.h>
using namespace std;

int main() {
    // Mở file để đọc và ghi dữ liệu
    freopen("ROBOTCHAR.INP", "r", stdin);
    freopen("ROBOTCHAR.OUT", "w", stdout);

    string s;
    cin >> s;

    vector<int> lastPos(26, -1); // Vị trí xuất hiện gần nhất của mỗi ký tự A-Z : Từ 0-->25

    int maxLen = 0;
    int left = 0, right = 0;
    int n = s.length();

    while (right < n) 
    {
        char c = s[right];

        // Nếu c đã xuất hiện trong cửa sổ hiện tại → cần cập nhật left
        if (lastPos[c - 'A'] >= left) 
        {
            left = lastPos[c - 'A'] + 1;
        }

        // Cập nhật vị trí xuất hiện gần nhất của c

        lastPos[c - 'A'] = right;

        // Cập nhật độ dài lớn nhất của chuỗi con không lặp

        maxLen = max(maxLen, right - left + 1);

        // Di chuyển con trỏ phải sang ký tự tiếp theo

        right++;
    }

    cout << maxLen << endl;
    return 0;
}

📋 Bảng mô tả thuật toán Sliding Window với chuỗi "ACBCA"
left (trước) right Ký tự s[right] lastPos trước khi cập nhật Điều kiện lặp? (lastPos[c] ≥ left) left (sau cập nhật) Cập nhật lastPos[c] maxLen
0 0 A lastPos[A] = -1 ❌ Không lặp 0 lastPos[A] = 0 1
0 1 C lastPos[C] = -1 ❌ Không lặp 0 lastPos[C] = 1 2
0 2 B lastPos[B] = -1 ❌ Không lặp 0 lastPos[B] = 2 3
0 3 C lastPos[C] = 1 ✅ Có lặp (1 ≥ 0) 2 lastPos[C] = 3 2
2 4 A lastPos[A] = 0 ❌ Không lặp (0 < 2) 2 lastPos[A] = 4 3

Kết luận:
  • Độ dài chuỗi con dài nhất không lặp ký tự là 3.
  • Các chuỗi con hợp lệ dài nhất: "CBA" hoặc "BCA".


Bình luận

Hãy đọc nội quy trước khi bình luận.

Không có bình luận tại thời điểm này.