from typing import List
def getKmpNext(data: List) -> List[int]:
next = [0 for _ in range(len(data))]
next[0] = -1
j, k = 0, -1
while j < len(data) - 1:
if k == -1 or data[j] == data[k]:
j, k = j + 1, k + 1
next[j] = k
else:
k = next[k]
return next
# 预处理先把状态转移的边算出来
N = int(input())
edge = {}
T = input()
next = getKmpNext(T)
for j in range(len(T)):
for ch in 'abcdefghijklmnopqrstuvwxyz':
if ch == T[j]:
edge[(j, ch)] = j + 1
else:
jj = j
while T[jj] != ch:
jj = next[jj]
if jj == -1:
break
edge[(j, ch)] = jj + 1
M = len(T)
# dp(i, j)表示的是原字符串和模式串的KMP匹配位置为i和j这样一种匹配状态是多少个可能的j的变化序列构造出来的
# 只要有一个j的变化序列能够构造出(i, j)这种状态,就存在一种长度为i的不包含子串T的字符串,
# 同一个i所有的dp(i,j)加起来等价于所有不包含模式串的长度为i-1的原字符串数量
dp = [[0] * M for _ in range(N + 1)]
dp[0][0] = 1
for i in range(N):
for j in range(M):
for ch in 'abcdefghijklmnopqrstuvwxyz': # 枚举i位置的字符的26种可能
next_j = edge[(j, ch)]
if next_j >= 0 and next_j < M:
dp[i + 1][next_j] += dp[i][j]
print(sum(dp[N]) % 1000000007)
AcWing 状态机DP相关问题 1052. 设计密码 KMP状态机模型,有点难想到
猜你喜欢
转载自blog.csdn.net/xiaohaowudi/article/details/107719595
今日推荐
周排行