Truy vấn kiểm tra xâu palindrome
2017-08-01Đề bài
Cho xâu s có độ dài n và q truy vấn, mỗi truy vấn là hai số “l r”: xâu con s từ vị trí l đến r có phải là xâu palindrome hay không?
Giới hạn:
- 1 ≤ n ≤ 5000
- 1 ≤ q ≤ 106
- 0 ≤ l ≤ r < n
Định dạng test
Input:
- Dòng đầu tiên là xâu s (không chứa khoảng trắng).
Output:
- q dòng, mỗi dòng là 1/0 trả lời cho q truy vấn.
Ví dụ:
Thuật toán
Gọi dp[i][j] nhận giá trị là true/false nếu xâu con từ i đến j là xâu palindrome, độ dài của xâu con này là len = j - i + 1. Ta có công thức truy hồi sau:
- Nếu len = 1: dp[i][j] = dp[i][i] = true.
- Nếu len = 2: dp[i][j] = (s[i] == s[j]).
- Ngược lại: dp[i][j] = (s[i] == s[j]) && (dp[i+1][j-1]).
Dễ thấy mảng dp được tính theo thứ tự tăng dần độ dài của xâu con.
Source code
Ngôn ngữ: C++.
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
const int N = 1005 + 5;
string s;
bool dp[N][N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// init
cin >> s;
int n = sz(s);
// dp
for(int len = 1; len <= n; len++)
for(int l = 0; l < n - len + 1; l++) {
int r = l + len - 1;
// corner cases
if (len == 1) {
dp[l][r] = true;
continue;
}
if (len == 2) {
dp[l][r] = (s[l] == s[r]);
continue;
}
dp[l][r] = (s[l] == s[r]) && dp[l+1];
}
// answer queries
int q; cin >> q;
while(q--) {
int l, r; cin >> l >> r;
cout << dp[l][r] << '\n';
}
return 0;
}
Độ phức tạp
O(n2 + q)