# UOJ005 - Zoo
Submit Your Solution (opens new window)
TIP
This problem is from NOI 2014.
# Description
The zoo director is teaching animals the KMP algorithm. In KMP, we have meaning the length of the longest substring of which is both prefix and suffix of and is not itself. The zoo director is not satisfied with that and further asks animals to find , which is the number of substrings of which are both prefix and suffix of , and the prefix and the suffix do not overlap. Can you write a program for that to help the animals?
You only need to output .
# Input
- The first line contains one integer (), number of test cases.
- The following lines each contain a string () which consists of lower case letters only.
# Output
lines for test cases. Every line contains one integer, the result for string in this test case.
# Samples
# Input 1
3
aaaaa
ab
abcababc
2
3
4
# Output 1
36
1
32
2
3
# Tutorial
Hint 1
Use Z-Algorithm.
Hint 2
Each (we need to constraint it below since overlapping is not allowed) will contribute to . So we can use a difference array and then get the values of each .
Code (C++)
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
vector<int> z_function(string s) {
int n = (int)s.size();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}
int main() {
int t;
cin >> t;
while (t--) {
string s;
cin >> s;
vector<int> z = z_function(s);
int n = (int)s.size();
vector<int> diff(n + 1);
for (int i = 1; i < n; ++i) {
int zi = min(z[i], i);
diff[i]++, diff[i + zi]--;
}
vector<int> num(n);
for (int i = 1; i < n; ++i)
num[i] = num[i - 1] + diff[i];
ll ans = 1;
for (int ni : num)
ans = ans * (ni + 1) % MOD;
cout << ans << endl;
}
}
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
41
42
43