AcWing 1052. 设计密码
原题链接
中等
作者:
皓首不倦
,
2020-07-25 03:00:28
,
所有人可见
,
阅读 587
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)