找回密码
 立即注册
首页 业界区 安全 S002 字符串构造 最长相等真前后缀 CF1029A ...

S002 字符串构造 最长相等真前后缀 CF1029A

挫莉虻 1 小时前
CF1029A - CodeForces
题意:给定一个字符串 \(t\) 构造最小的一个字符串 \(s\) ,要求字符串 \(s\) 恰好有 \(k\) 个子串等于 \(t\) 。
第一眼想到的是周期。但是有的情况有重叠不能直接将 \(t\) 复制 \(k\) 份。这就不是最小了,那么如何求最小呢?
这个重叠的话与前后缀有关。如果一个字符串的前缀等于后缀,大小为 \(L\) 的话,那么这 \(L\) 部分重叠了,可以重复利用,我们只需要在后面接上 \(t[L:]\) 即可,因为前面的后缀可以当当前的前缀使用。这就是重叠。
因为要最小,所以这个问题就转化为求最长相等真前后缀。 \(L\) 大 \(n-L\) 就小,求出 \(L\) 后只需要在原串上后面加上 \((k-1)\) 个 \(t[L:]\) 。
因为数据很小可以直接 \(O(n^2)\) ,也可以使用前缀函数求出 \(\pi\) 数组, \(\pi\) 数组的 \(\pi[n-1]\) 就是最长的 Border 。
具体代码为
  1. import sys
  2. Max = lambda x, y: x if x > y else y
  3. Min = lambda x, y: x if x < y else y
  4. input_type = 1
  5. if input_type:
  6.     inp = lambda: sys.stdin.readline().strip()
  7.     II = lambda: int(inp())
  8.     MII = lambda: map(int, inp().split())
  9.     LII = lambda: list(MII())
  10. else:
  11.     input_data = sys.stdin.read().split()
  12.     it = iter(input_data)
  13.    
  14.     II = lambda: int(next(it))
  15.     SI = lambda: next(it)
  16.    
  17.     if not input_data:
  18.         sys.exit()
  19. def border(s):
  20.     n = len(s)
  21.     L = 0
  22.     for i in range(1, n):
  23.         if s[:i] == s[n-i:n]:
  24.             L = i
  25.     return L
  26. def main():
  27.     n, k = MII()
  28.    
  29.     s = inp()
  30.     pi = [0] * n
  31.     for i in range(1, n):
  32.         j = pi[i - 1]
  33.         while j > 0 and s[i] != s[j]:
  34.             j = pi[j - 1]
  35.         if s[i] == s[j]:
  36.             j += 1
  37.         pi[i] = j
  38.    
  39.     L = pi[n - 1]
  40.    
  41.     print(s + (k - 1) * (s[L:]))
  42. if __name__ == "__main__":
  43.     main()
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册