hdu 3374 String Problem 最大最小表示+kmp

缘起

继续熟练最大最小表示 ~ hdu 3374 String Problem

分析

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
一个字符串可以通过循环搞出若干个. 例如SKYLONG可以通过移位搞出7个

SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7

输出最大最小表示是从哪一位开始(如果有多个,输出最小下标),而且输出数量.

【输入】
多样例, 每个样例占一行. 每行是一个不超过100w个小写字符的字符串.

【输出】
对每个样例输出四个整数, 分别是字典序最小的下标以及出现的次数. 字典序最大的下标以及出现的次数.

【样例输入】
abcder
aaaaaa
ababab

【样例输出】
1 1 6 1
1 6 1 6
1 3 2 3

【限制】
1s

字典序最大最小通过字符串的最大最小表示来切(算法讲解参见【1】). 而出现次数通过kmp来切. 因为显然字典序最小的字符串和字典序最大的字符串出现的次数相同. 而且就是循环节出现的次数(为什么? 因为你可以将字典序最小的那个串移动到最前面即可, 例如 bababa, 则字典序最小的是ababab, 就是6/2=3,2是循环节的大小) 不会kmp搞字符串循环节的算法见【2】

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
//#define LOCAL
const int maxn = 1e6+5;
char s[maxn];
int nnext[maxn], len;

int getmin(char *s)
{
int i = 0, j = 1, k = 0, t;
while(i<len && j<len &&k<len)
{
t = s[(i+k)%len] - s[(j+k)%len];
if (!t)
{
++k;
continue;
}
t>0?i+=k+1:j+=k+1;
if (i==j)
{
++j;
}
k = 0;
}
return min(i,j);
}

int getmax(char *s)
{
int i = 0, j = 1, k = 0, t;
while(i<len && j<len &&k<len)
{
t = s[(i+k)%len] - s[(j+k)%len];
if (!t)
{
++k;
continue;
}
t<0?i+=k+1:j+=k+1; // 最大表示和最小表示的唯一区别
if (i==j)
{
++j;
}
k = 0;
}
return min(i,j);
}

void makenext()
{
nnext[1] = 0;
for (int i = 2,k;i<=len+1;i++)
{
k = nnext[i-1];
while(k && s[k]!=s[i-1])
{
k = nnext[k];
}
nnext[i] = k+1;
}
}

int main()
{
#ifdef LOCAL
freopen("d:\\data.in", "r", stdin);
// freopen("d:\\my.out", "w", stdout);
#endif
while(~scanf("%s", s+1))
{
len = strlen(s+1);
int mmin = getmin(s+1)+1, mmax = getmax(s+1)+1;
makenext();
int sz = len-nnext[len+1]+1;
sz = len%sz?1:len/sz;
printf("%d %d %d %d\n", mmin, sz, mmax, sz);
}
return 0;
}

ac情况

Status Accepted
Time 280ms
Memory 6624kB
Length 1182
Lang C++
Submitted 2019-10-30 17:23:05
Shared
RemoteRunId 31189986

参考

【1】https://yfsyfs.github.io/2019/10/30/hdu-2609-How-many-%E6%9C%80%E5%A4%A7%E6%9C%80%E5%B0%8F%E8%A1%A8%E7%A4%BA%E6%9D%BF%E9%A2%98/

【2】https://yfsyfs.github.io/2019/10/23/poj-2406-Power-Strings-KMP/