ps:teflib:string
목차
string.py
- 구버전 코드는 (old) string.py로.
z_array
코드
# N z_array
# I {"version": "1.0"}
def z_array(s: str) -> list[int]:
"""Returns Z array of given string. (z[0]==len(s))"""
n = len(s)
l, r, z = 0, 0, [0]
for i in range(1, n):
z_i = min(r - i + 1, z[i - l]) if i <= r else 0
while i + z_i < n and s[z_i] == s[i + z_i]:
z_i += 1
if i + z_i - 1 > r:
l, r = i, i + z_i - 1
z.append(z_i)
z[0] = n
return z
설명
- z algorithm을 적용해서 z-array를 계산한다
이 코드를 사용하는 문제
Trie
코드
# N Trie
# I {"version": "2.0", "typing": ["Generator", "Generic", "Iterable", "TypeVar"]}
_CharLike = TypeVar('_CharLike')
_StrLike = Iterable[_CharLike]
_TrieNode = int
class Trie(Generic[_CharLike]):
def __init__(self, words: Iterable[_StrLike] = ()):
self.ROOT = 0
self.word_counts = [0]
self.child_counts = None
self.children = [{}]
for word in words:
self.add(word)
def add(self, word: _StrLike) -> _TrieNode:
"""Adds the given word to trie and returns a node for it."""
node = self.ROOT
for ch in word:
try:
node = self.children[node][ch]
except KeyError:
new_node = len(self.children)
self.children.append({})
self.word_counts.append(0)
self.children[node][ch] = new_node
node = new_node
self.word_counts[node] += 1
return node
def prefixes(self, word: _StrLike) -> Generator[_TrieNode, None, None]:
"""Yields all nodes for prefixes of the given word."""
node = self.ROOT
return ((node := self.children[node][ch]) for ch in word)
def nodes(self) -> Iterable[_TrieNode]:
return range(1, len(self.children))
def words(self) -> Iterable[_TrieNode]:
return (x for x in self.nodes() if self.word_counts[x] > 0)
def get_child_count(self, node: _TrieNode) -> int:
def count_rec(node):
if self.child_counts[node] is None:
self.child_counts[node] = sum(
count_rec(child) + self.word_counts[child]
for child in self.children[node].values())
return self.child_counts[node]
if not self.child_counts:
self.child_counts = [None] * len(self.children)
return count_rec(node)
설명
- 트라이 (Trie) 참고
이 코드를 사용하는 문제
palindrome_radiuses
코드
# N palindrome_radiuses
# I {"version": "1.01", "typing": ["Sequence", "TypeVar"], "const": ["T"]}
def palindrome_radiuses(text: Sequence[T]):
"""Implementation of Manacher's algorithm."""
end = center = -1
radiuses = []
for i in range(len(text)):
rad = min(end - i - 1, radiuses[center * 2 - i]) if i < end else 0
left = i - rad - 1
right = i + rad + 1
try:
while text[left] == text[right]:
rad += 1
left -= 1
right += 1
except IndexError:
pass
if right > end:
center, end = i, right
radiuses.append(rad)
return radiuses
설명
- Manacher's algorithm 을 구현한 것으로 가장 긴 팰린드롬 부분문자열 (Longest Palindromic Substring)을 참고.
- 원본 문자열을 그대로 인자로 넘겨서 돌리면 홀수 길이 팰린드롬에 대한 정보밖에 얻지 못하므로, 대부분의 경우에는 문자열의 각 문자 사이에 특수문자를 추가하는 식으로 문자열을 변형하여서 인자로 넘긴다.
이 코드를 사용하는 문제
출처 | 문제 번호 | Page | 레벨 |
---|---|---|---|
BOJ | 11046 | 팰린드롬?? | 플래티넘 5 |
BOJ | 14444 | 가장 긴 팰린드롬 부분 문자열 | 플래티넘 5 |
BOJ | 13275 | 가장 긴 팰린드롬 부분 문자열 | 플래티넘 5 |
프로그래머스 | 12904 | 가장 긴 팰린드롬 | Level 3 |
BOJ | 18171 | ABB | 플래티넘 4 |
BOJ | 16163 | #15164번_제보 | 플래티넘 5 |
ps/teflib/string.txt · 마지막으로 수정됨: 2023/05/27 15:23 저자 teferi
토론