#odb0004. 最小循环子数组【B卷 200分】-字符串
题目描述
给定一个由若干整数组成的数组nums,请检查数组是否是由某个子数组重复循环拼接而成,请输出这个最小的子数组。
输入描述
第一行输入数组中元素个数n,1 ≤ n ≤ 100000
第二行输入数组的数字序列nums,以空格分割,0 ≤ nums[i] < 10
输出描述
输出最小的子数组的数字序列,以空格分割;
备注
数组本身是其最大的子数组,循环1次可生成的自身;
用例1
输入
9
1 2 1 1 2 1 1 2 1
输出
1 2 1
说明
数组[1,2,1,1,2,1,1,2,1] 可由子数组[1,2,1]重复循环3次拼接而成
解答
# KMP 算法
# 如果字符串s是由最小重复子串x重复产生的,
# 则最小重复子串x的长度 = s.length - 最长相同前后缀.length# 输入获取
n=int(input())
nums=list(map(int,input().split()))def getNext():# 创建长度为n的next数组,初始值全为0nxt = [0] * n# 初始化指针:j遍历字符串,k跟踪当前匹配的前缀长度j = 1 # 从第二个字符开始遍历k = 0 # 当前匹配的前缀长度# 遍历整个数组(从索引1开始)while j < n:# 当前字符与前缀的下一个字符匹配J=nums[j] # 短匹配串元素K=nums[k] # 长主串元素if J == K:nxt[j] = k + 1 # 记录匹配长度j += 1 # 移动主指针k += 1 # 增加前缀长度,指针后移else:if k > 0: # 不是长主串的第一个元素# 利用已计算的next值回溯(KMP核心优化)k = nxt[k - 1]else:# 无法回溯时,当前字符的next值为0nxt[j] = 0j += 1return nxt # 返回计算完成的next数组# 算法入口
def getResult():# KMP算法 求nxt数组nxt = getNext()# 最长相同前后缀长度m=nxt[n-1]# 最小重复子串的长度length=n-m if n%(n-m)==0 else nreturn " ".join(map(str,nums[0:length]))# 算法调用
print(getResult())