HDU-1358 Period

题目链接

题意概括:

找出从第二个字符开始,之前所有的字符是否是循环串,如果是,输出当前字符的下标(此题下标从1开始)和周期(T>1)

Just read code.

code

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
41
42
43
44
45
46
47
48
49
50
//本题利用KMP算法中求Next[]数组的性质可以解决;
//即如果一个字符串为循环串时,(例如adcabcabc)那么它的next[]数组满足下面性质:
//1、len%(len-pre[len])==0;2、len/(len-pre[len])就是循环的次数;这里len是字符串的长度,pre[]是next[]数组;

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int maxn = 1e6 + 9;
int pre[maxn], n;
char s[maxn];
void pre_fun()
{
for (int i = 1; i <= n; ++i) {
int j = pre[i - 1];
while (j > 0 && s[i] != s[j])
j = pre[j - 1];
if (s[i] == s[j])
j++;
pre[i] = j;
}
} //注意不同的next数组习惯,使用前应该输出next数组查看
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);

int ca = 0;
while (cin >> n, n) {
cin >> s;
pre_fun();
// for (int i =0 ; i < n; ++i)
// cout << pre[i] << ' ';
// cout<<endl;
cout << "Test case #" << ++ca << endl;

for (int i = 0; i < n; ++i) {
// cout << pre[i] << ' ';
if (pre[i] < 1)
continue;
int j = i + 1 - pre[i]; //显然,下标为0,字符串长度为1
// cout<<j<<' ';
if (j > 0 && (i + 1) % j == 0) {
cout << i + 1 << ' ' << (i + 1) / j << endl;
}
}

cout << endl;
}
return 0;
}
0%