题目链接
https://www.lanqiao.cn/problems/1071/learning/
题目大意
找出给定字符串每个前缀中的最长真前缀,使得该前缀剩下的真后缀是上述真前缀的前缀
(真前/后缀:不包含自身的非空前/后缀)。
并统计这些最长真前缀的长度之和(不存在记为0)。
解题思路
40 p t s 40pts 40pts
暴力循环模拟
1、遍历每一个前缀
2、从大到小取proper前缀,如果满足取完proper前缀的后缀是所取proper前缀的前缀,则返回最大周期长度
# -*- coding: utf-8 -*-
# @Author : BYW-yuwei
# @Software: python3.8.6
from math import ceil
def is_prefix(s, sub):
return s[: len(sub)] == sub
def max_circle(s):
tail = len(s) - 1
middle = ceil(len(s) / 2) - 1
for size in range(tail, middle, -1):
pre, suf = s[: size], s[size:]
if is_prefix(pre, suf):
return size
return 0
if __name__ == '__main__':
n = int(input())
s = input()
cnt = 0
for i in range(2, n + 1):
cnt += max_circle(s[: i])
print(cnt)
100 p t s 100pts 100pts
1、对于字符串
s
s
s,其前缀函数定义为:对于每个下标
i
i
i,
s
[
0
:
i
]
s[0:i]
s[0:i] 的真前后缀最长相等长度。
2、在此基础上,考虑真前后缀的最短相等长度,记为最短前缀函数。
∣
s
[
0
:
i
]
∣
−
m
i
n
(
s
[
0
:
i
]
的公共前缀后缀
)
|s[0:i]|−min(s[0:i]的公共前缀后缀)
∣s[0:i]∣−min(s[0:i]的公共前缀后缀)
希望周期尽可能的大,也就是希望真前后缀相等长度尽可能的短
最后只需要根据题意,排除前后缀重叠的情况,即可得到答案。
AC_Code
python程序:
# -*- coding: utf-8 -*-
# @Author : BYW-yuwei
# @Software: python3.8.6
def max_fix(s):
max_same = [0] * len(s)
for i in range(1, len(s)):
j = i - 1
while j >= 0:
pi = max_same[j]
if s[i] == s[pi]:
max_same[i] = pi + 1
break
j = pi - 1
return max_same
def min_fix(s):
min_same = max_fix(s)
for i in range(1, len(s)):
j = i # initial j as i > 0
while min_same[j]: # ensure j and pi > 0
min_same[i] = min_same[j]
j = min_same[j] - 1 # worst j is 0
return min_same
if __name__ == '__main__':
n = int(input())
s = input()
min_same = min_fix(s)
cnt = 0
for i in range(1, n):
if min_same[i]:
size = i + 1
if min_same[i] <= size // 2:
cnt += size - min_same[i]
print(cnt)