前缀函数和next数组基本上是一个东西,但储存的内容不同。
他们是kmp算法的基础。但真的不太好理解,以及不好写,背不过。
前缀函数π(i)可以在O(n)的时间计算出来数组内每个前缀的前缀函数。
例题: 4808. 构造字符串
这题暴力能过,但还是前缀函数nb。
# Problem: 构造字符串
# Contest: AcWing
# URL: https://www.acwing.com/problem/content/4811/
# Memory Limit: 256 MB
# Time Limit: 1000 msimport sys
import bisect
import random
import io, os
from bisect import *
from collections import *
from contextlib import redirect_stdout
from itertools import *
from array import *
from functools import lru_cache
from types import GeneratorType
from heapq import *
from math import sqrt, gcd, infif sys.version >= '3.8': # ACW没有combfrom math import combRI = lambda: map(int, sys.stdin.buffer.readline().split())
RS = lambda: map(bytes.decode, sys.stdin.buffer.readline().strip().split())
RILST = lambda: list(RI())
DEBUG = lambda *x: sys.stderr.write(f'{str(x)}\n')MOD = 10 ** 9 + 7def prefix_function(s):"""计算s的前缀函数"""n = len(s)pi = [0] * nfor i in range(1, n):j = pi[i - 1]while j > 0 and s[i] != s[j]:j = pi[j - 1]if s[i] == s[j]:j += 1pi[i] = jreturn pi
# ms
def solve():n, k = RI()t, = RS()mx = prefix_function(t)[-1]if mx == 0:return print(t * k)suf = t[mx:]print(t + suf * (k - 1))if __name__ == '__main__':solve()
链接: 1367. 二叉树中的链表
试了下树上kmp是负优化,但可能是数据问题。
class Solution:def isSubPath(self, head: ListNode, root: TreeNode) -> bool:path = []while head:path.append(head.val)head = head.nextn = len(path)def get_next(p):n = len(p)nxt = [0]*nnxt[0] = -1j,k=0,-1while j < n-1:if k == -1 or p[j] == p[k]:j+=1k+=1if p[j] == p[k]:nxt[j] = nxt[k]else:nxt[j] = k else:k = nxt[k]return nxtnxt = get_next(path)# print(nxt)def dfs_kmp(tree, j):if j == n:return Trueif not tree:return Falseif j == -1 or tree.val == path[j]:return dfs_kmp(tree.left,j+1) or dfs_kmp(tree.right,j+1)else:return dfs_kmp(tree,nxt[j])
链接: 28. 找出字符串中第一个匹配项的下标
class Solution:def strStr(self, haystack: str, needle: str) -> int:m,n = len(haystack),len(needle)# def get_next(p):# n = len(p)# nxt = [-1] * n# j, k = 0, -1# while j < n - 1:# if k == -1 or p[j] == p[k]:# j += 1# k += 1# if p[j] == p[k]:# nxt[j] = nxt[k]# else:# nxt[j] = k# else:# k = nxt[k]# return nxt# nxt = get_next(needle)# print(nxt)# i = j = 0 # while i < m and j < n:# if j == -1 or haystack[i] == needle[j]:# i += 1# j += 1# else:# j = nxt[j]# if j == n:# return i - j # return -1def prefix_function(s):"""计算s的前缀函数"""n = len(s)pi = [0] * nfor i in range(1, n):j = pi[i - 1]while j > 0 and s[i] != s[j]:j = pi[j - 1]if s[i] == s[j]:j += 1pi[i] = jreturn pipi = prefix_function(needle)print(pi)i ,j = 0,0 while i < m and j < n:while j > 0 and haystack[i] != needle[j]:j = pi[j-1]if haystack[i] == needle[j]: j += 1if j == n:return i - j + 1i += 1return -1