classNode:__slots__='son','fail','last','sz'def__init__(self):self.son=[None]*26self.fail=None# u 的 fail 指向 v,v 是树中 u 的最长后缀self.last=None# u 的 last 指向 v,v 是树中 u 的最长后缀且是某个单词的结尾self.sz=0# 假如 u 是某个单词的结尾,sz 即是单词长度classAC:def__init__(self):self.root=p=Node()dum=Node()# 哑节点,方便后续 builddum.son,p.fail,p.last=[p]*26,dum,pdefadd(self,s,w):p=self.rootforcins:c=ord(c)-ord('a')ifnotp.son[c]:p.son[c]=Node()p=p.son[c]p.sz=len(s)defbuild(self):Q=deque([self.root])whileQ:u=Q.popleft()forc,soninenumerate(u.son):ifson:son.fail=u.fail.son[c]son.last=son.failifson.fail.szelseson.fail.lastQ.append(son)else:# 虚拟子节点,失配时直接跳到下一个匹配位置u.son[c]=u.fail.son[c]