---
# System prepended metadata

title: Solution Bài 2 TS10 ĐN

---

# Solution Bài 2 TS
Subtask 1:
- Giới hạn: s ≤ 500
- Hướng giải: Duyệt qua tất cả các chuỗi con có thể có trong chuỗi s và kiểm tra xem chuỗi con đó có đối xứng hay không. Nếu đối xứng, tăng biến đếm lên 1.

Subtask 2:
- Giới hạn: s ≤ 1000
- Hướng giải: Sử dụng phương pháp DP để xác định các chuỗi con đối xứng. Sử dụng một ma trận isPalindrome[n][n] để lưu trữ thông tin về tính đối xứng của các chuỗi con. Duyệt qua tất cả các độ dài chuỗi con từ 1 đến n, sau đó duyệt qua tất cả các vị trí i trong chuỗi s. Kiểm tra xem chuỗi con từ vị trí i đến i + len - 1 có đối xứng hay không và cập nhật giá trị trong ma trận isPalindrome. Tăng biến đếm lên 1 cho mỗi chuỗi con đối xứng tìm thấy.

Subtask Full:
- Giới hạn: s ≤ 1e5
- Hướng giải: Sử dụng phương pháp Manacher để tìm số lượng chuỗi đối xứng trong chuỗi s. Xây dựng chuỗi p bằng cách thêm ký tự đặc biệt vào giữa mỗi ký tự trong chuỗi s và ở đầu và cuối chuỗi. Sử dụng một mảng a để lưu trữ thông tin về độ dài chuỗi đối xứng tại mỗi vị trí trong chuỗi p. Duyệt qua từng vị trí trong chuỗi p và tính giá trị tương ứng của mảng a bằng phương pháp Manacher. Cuối cùng, tính tổng độ dài chuỗi đối xứng từ các giá trị trong mảng a và trả về kết quả.

Đây là đoạn code tham khảo:
```cpp=
#include<bits/stdc++.h>
#define Nhin_lai_cuoc_doi() ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
const int maxsub1 = 500;
const int maxsub2 = 1000;
const int full = 1e5 + 33;
string pre(string s) {
    string p = "#";
    p.reserve(2 * s.length() + 1);
    for (int i = 0; i < s.length(); i++) {
        p += s[i];
        p += '#';
    }
    return p;
}
bool palin(string s) {
    long long int l = 0, r = s.length() - 1;
    while (l < r) {
        if (s[l] != s[r])
            return false;
        l++;
        r--;
    }
    return true;
}
long long sub1(string s) {
    long long res = 0, n = s.length();
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            string substring = s.substr(i, j - i + 1);
            if (palin(substring))
                res++;
        }
    }
    return res;
}

long long sub2(string s) {
    long long res = 0, n = s.length();
    vector<vector<bool>> ispalin(n, vector<bool>(n, false));
    for (int i = 0; i < n; i++) {
        ispalin[i][i] = true; 
        res++;                     
    }
    for (int len = 2; len <= n; len++) {
        for (int i = 0; i < n - len + 1; i++) {
            int j = i + len - 1;
            if (s[i] == s[j]) {
                if (len == 2 || ispalin[i + 1][j - 1]) {
                    ispalin[i][j] = true;
                    res++;
                }
            }
        }
    }
    return res;
}

long long subfull(string s) {
    string p = pre(s);
    long long n = p.length();
    vector<long long> a(n, 0);
    long long c = 0, rr = 0, m = 0;
    for (int i = 0; i < n; i++) {
        if (i < rr) {
            int j = 2 * c - i;
            a[i] = min(rr - i, a[j]);
        }
        long long l = i - (a[i] + 1), r = i + (a[i] + 1);
        while (l >= 0 && r < n && p[l] == p[r]) {
            a[i]++;
            l--;
            r++;
        }
        if (i + a[i] > rr) {
            c = i;
            rr = i + a[i];
        }
        m = max(m, a[i]);
    }
    long long res = 0;
    for (int i = 0; i < a.size(); i++) {
        int len = a[i];
        res += (len + 1) / 2;
    }
    return res;
}
int main() {
	Nhin_lai_cuoc_doi();
    freopen("DOIXUNG.INP", "r", stdin);
    freopen("DOIXUNG.OUT", "w", stdout);
    string s;
    getline(cin, s);
    long long res;
    if (s.length() <= maxsub1) res = sub1(s);
    else if (s.length() <= maxsub2) res = sub2(s);
    else res = subfull(s);
    printf("%lld\n", res);
    return 0;
}


```


