2021.2.2做题小结

1.[POJ1816]Wild_Words

题意:先给你n个字符串,这些字符串包含小写字母,‘?’和 * ,其中 ?可以表示任意一个字符, * 可以表示任意长度的任意字符,(包括0个) m次询问,每次给你一个字符串,问你它和哪些字符串匹配

思路:trie,考虑到一个节点可能有多个子节点可以走,可以把匹配函数写成递归的形式。

具体就是 void find(int st,int ed,int u),其中st表示匹配到模式串的哪个位置,ed 标识结束,u 是trie 位置所在。注意到 * 的可延伸性,所以一种方式是 F(i,st,ed) 枚举延伸到什么位置,一种方式给 u 加上一个 * 的子节点

2.Keywords_search

题意:给定n个长度不超过50的小写字母组成的单词,以及一篇长为m的文章,问有多少个单词在文章出现。

思路:AC自动机模板

3.「JSOI2012」玄武密码

题意:母串上的最长匹配长度

思路:考虑 AC 自动机,我们建出 Trie 图然后用母串来在上面跑。

每一个能匹配的位置,它 fail 的位置也一定可以匹配,我们就跳 fail 把经过的节点的值赋为 1 ,表示这个位置可以匹配。

然后我们每一个模式串,找到它在 Trie 树上最深的可以匹配的节点来计算答案即可。

注意:还有一种统计答案的方式是在跳 fail 的时候计算答案

但为了知道一个节点被那些字串经过( 统计答案是对一个字串 ),我们需要用一个vector< int >num[i] 记录 trie 上经过节点 i 的字串的编号(在insert的时候可以就可以顺便做了),于是 MLE

4.[USACO15FEB]Censoring Gold

题意:给你一个文本串,和一大堆模式串,现在进行如下操作:找到出现位置最靠前的模式串 and 删掉它 保证没有任何一个字符串是另一个字符串的子串。

思路:首先看到 [USACO15FEB]Censoring (Silver) (in 2021.1.31 小结)

那道题的AC思路是这样的:KMP扫描字符串S,用栈存下扫过的部分,及当时字符串T匹配到的位置id

如果匹配成功,则在栈中删除串T,同时id更新为栈顶的id(删除子串后出现的新子串只会在接合处产生)匹配完后输出栈即可,时间复杂度O(n)

对比两道题目,发现区别在于 单/多模式串,多模式串问题 AC自动机即可。注意,由于 AC 自动机涉及到字串的跳转,所以还需要一个栈来记录当前匹配的位置

5.「POI2000」病毒

题意:求一个无限长的串,不包含给定的模式串。

思路:父节点到子节点看作一条单向边,失配指针nxt[]指向的也看作一条单向边,最后会形成一个图。 如果在这个图中找到一个环,且不存在结束标记,那么存在一个以环为循环的无限长的安全代码。 做法:AC自动机+DFS

注意:如果一个点的 fail 指向的位置有结束标记,这个点即使没有结束标记也需要加上结束标记

这是因为 fail 的定义,指向的是当前字符串的后缀。如果 fail 指向结束,即当前串包含一个完整的模式串,当然也不能取

6.「JSOI2007」文本生成器

题意:给定一些模式串,求长度为m的所有文本串的个数,且该文本串至少包括一个模式串,答案对10007取模

思路:AC自动机+dp。第一次接触。

最开始拿到这道题是完全懵逼的,涉及到多个字符串匹配,想到AC自动机。朴素想法是把所有的文本串都插入一颗 trie,然后做AC自动机。发现长度为 m 的文本串有 26^m 个,显然不可行。

那么只能把模式串插入 trie 了,求包含的个数怎么求?枚举文本串?显然不可行。懵逼,看题解(https://www.cnblogs.com/refun/p/8706911.html)

正解:用所有的情况减去不可读的情况(跑不到单词结尾节点的情况)。不可读的情况数量可以用 d p 求。设 f[i][j] 表示匹配了 i 个字符,现在到 j 号节点的不可读情况数量,从父亲往儿子转移。

注意:同第5题,if(isend[fail[trie[u][i]]])isend[trie[u][i]]=1;

7.基数排序

题意:RT

思路:模板。基数排序主要用于处理值域小的排序问题

posted @ 2021-02-02 22:57  _Famiglistimo  阅读(64)  评论(0编辑  收藏  举报