摘要: 感谢csimstu找了这么多好题啊~字符串哈希: 基本就用大质数乘幂了. 这些题其实都是后缀数组的基础题, 被我用哈希水了...POJ 1743 Musical Theme 男人八题中的一道POJ 3261 Milk PatternsPOJ 2774 Long Long Message后缀数组: 终于学会强大的后缀数组了. 倍增搞出sa和rank后, 顺带处理一个NX的height, 多个串的问题就是连起来做一遍后缀数组, 很多都是二分答案或是枚举答案并按height分组.POJ 3294 Life FormsPOJ 3581 SequencePOJ 3415 Common Substring 阅读全文
posted @ 2012-03-10 22:11 zcwwzdjn 阅读(452) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给出两个状态数不超过2000的DFA, 判断是否同构. 同构的意思是能识别的语言完全相同. 字符集最大26.简要分析:本来想把所有字符串从一个DFA里面搞出来, 再对另一个DFA进行黑箱测试, 但一看样例, 有环!!! 也就是说, 它们能识别的语言可以是无限的!于是就只好曓搜了, 用(i, j)二元组表示两台自动机分别在状态i和j, 从(0, 0)开始广搜, 搜出一个二元组(i, j), 则两台DFA同构的充分条件是状态i和状态j相同, 这里判断相同考虑两方面就行了: 是否同为final态(或者叫accept态?)或同不为, 转移方式是否完全相同. 若所有的二元组能满足, 则可以判断 阅读全文
posted @ 2012-03-10 22:01 zcwwzdjn 阅读(478) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给N个(N不超过5000)长度不超过30的仅有小写字母组成的字符串, 构造状态数最小的DFA.简要分析:有限自动机状态最小化似乎是有论文介绍高级方法的...我们学OI就不用那么专业了. 关于DFA的解释参考http://en.wikipedia.org/wiki/Deterministic_finite_automaton.首先Trie树肯定是DFA, 所以我们先把Trie建出来. 因为要保证简化后的DFA与Trie这个DFA同构, 而同构的含义是能识别的语言完全相同, 因为字符串没有无限长的, 所以不会有环, 即最终的DFA必定是DAG. 现在我们考虑合并Trie中的结点. 按照每 阅读全文
posted @ 2012-03-10 21:53 zcwwzdjn 阅读(768) 评论(0) 推荐(0) 编辑
摘要: 题目大意:输出第N大的包含666这个子串的正整数. N不大于50000000.简要分析:第一反应是某种数位DP, 第二反应是要匹配666, 建个自动机...只有4种状态的自动机. 0表示没有666且当前没有6, 1表示没有666且当前有一个6, 2表示没有666且当前有两个6, 3表示有666, 于是可以人肉出转移表trans. 定义f[i][j]为在j状态的字符串后输入i个字符能达到目标的方案数. 初始态是f[0][3] = 1, 转移方程f[i][j] = sigma(f[i-1][trans[j][k]]), k为10种转移. 构造答案时先算出位数dig, 再从dig高位往低位一位一位确 阅读全文
posted @ 2012-03-10 21:39 zcwwzdjn 阅读(556) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给你N个致病基因(长度各不超过20), 再给你一个DNA一条链的碱基序列(长度M不超过1000), 要求尽量少的修改碱基, 使得序列不含致病基因, 不能的话输出-1.简要分析:有赤裸裸的多模式串匹配, 当然要建立AC自动机了. 把一些状态标成致病态(当然把fail指针的信心合并过来). 设f[i][s]表示到DNA的第i个碱基, 在自动机上走到s状态, 至少的修改次数. 转移就枚举AGCT进行转移就行了, 注意不能走到致病状态. 于是答案为min{f[M][s]}, s为非致病状态. 有一种类似的问题M奇大无比, 而状态数又不多, 敏感的想到矩阵乘法就行了.代码实现:View Cod 阅读全文
posted @ 2012-03-10 21:30 zcwwzdjn 阅读(763) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给两个长度不超过100000的字符串, 一个是带有通配符?和*的模式串, 问能否匹配. 通配符不超过10个.简要分析:翻了网上盛传的一份讲AC自动机的论文(总觉得是生物论文), 学习了带通配符的匹配.因为*可以是任意长度, 所以我们可以去掉*, 得到若干子串, 我们找出这些子串能匹配的位置, 并尽量往前放, 看是否满足要求即可. 这里需要注意首为*或尾为*的情况, 其实就是子串匹配时是否需要匹配到头或是尾.于是问题变成了, 设文本串为S, 某一只含?和小写字母的模式串T, 去掉问号后得到若干子串P1, P2, P3, ...Pk, 每个子串结束的下标为L1, L2, L3, ...L 阅读全文
posted @ 2012-03-10 21:21 zcwwzdjn 阅读(1330) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给出N个带通配符(?和*)的模式串, M个询问, 询问一个给你的字符串能匹配哪些模式串. 模式串长度不超过6, 询问串长度不超过20.简要分析:带通配符AC自动机? 不是的, 看字符串的长度都那么小, 暴力一下就可以了. 把所有模式串丢到Trie里面, *和?也作为一种转移, 对于每个询问串, 暴力dfs就可以了.代码实现:View Code 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <vector> 5 #include <a 阅读全文
posted @ 2012-03-10 21:05 zcwwzdjn 阅读(363) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给你N个字符串, 你可以两两连接得到N * N个字符串, 问之中回文串的数量. N个字符串的长度和加起来不超过2000000.简要分析:无比恶心的题啊...我们顺次考虑每个字符串放在前面的情况. 假设字符串i放在前面, j放在后面, 那么这个串是回文有两种情况:1) 若i的长度小于j, 则i是j反串的前缀, 且j反串剩下的后缀是回文串.2) 若i的长度不小于j, 则j反串是i的前缀, 且i串剩下的后缀是回文串.于是大致的思路就有了, 把所有串的反串丢到Trie里面, 每个结点额外记录两个值: 从这个点往下走到叶子, 有多少串是回文; 在这个点结束的字符串有多少. 这两个值就分别对应前 阅读全文
posted @ 2012-03-10 20:59 zcwwzdjn 阅读(1268) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给一个R * C的字符矩阵, 找一个最小面积的矩阵, 能用它覆盖整个矩阵(所谓覆盖, 就是用这个小矩阵能拼凑出一个大矩阵包含原矩阵, 且左上角重合).简要分析:在草稿纸上画了一下后发现行和列是独立的, 可以分开做. 若第i行的字符串最小能被长为Li的字符串覆盖, 那么答案矩阵最小的列数就是各行Li的的最小公倍数.于是问题转化成了, 对每一行如何求Li. 设某一行字符串为s1s2..sM, L = Li, N = kL, 则字符串可以写成s1s2..sLs1s2..sL..s1s2..sLs(N + 1)s(N + 2)..sM的形式, 注意这时从1开始的后缀与从L + 1开始的后缀有 阅读全文
posted @ 2012-03-10 20:22 zcwwzdjn 阅读(603) 评论(0) 推荐(0) 编辑
摘要: 题目大意:一个字符串的重复数x的含义是, 它可以由至多x个相同的字符串连接而成. 现在给出一个长度为N的字符串, N不超过100000, 求出它的重复数最大且字典序最小的子串.简要分析:论文题, 思路很有意思. 我们定义重复的字符串为循环节, 那么我们就枚举循环节长度L, 那么如果答案存在, 则必定包含s[0], s[L], s[2 * L]等中相邻的连个. 我们再枚举j, 则相当于我们假定s[j * L]和s[(j + 1) * L]在答案中, 且s[j * L]在第一个循环节内. 这里我们需要求后缀j * L和后缀(j + 1) * L的最长公共前缀, 这个可以用后缀数组和ST算法做好预处 阅读全文
posted @ 2012-03-10 20:05 zcwwzdjn 阅读(1197) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给两个长度不超过100000的字符串A和B, 求三元组(i, j, k)的数量, 即满足A串从i开始的后缀与B串从j开始的后缀有长度为k的公共前缀, 还要求k不小于某个给你的数K.简要分析:如果i后缀与j后缀的LCP长度为L, 在L不小于K的情况下, 它对答案的贡献为L - K + 1. 于是我们可以将两个串连起来, 中间加个奇葩的分隔符, 做一遍后缀数组, 并按height数组的值对后缀分组, 保证同组内的后缀间的LCP不小于K. 显然不同组间的答案是独立的, 我们可以单独处理每一组. 于是问题变成了: 在每一组内, 对每个A的后缀, 算出它之前B的后缀与之LCP的和(其实是LCP 阅读全文
posted @ 2012-03-10 19:50 zcwwzdjn 阅读(1636) 评论(0) 推荐(0) 编辑
摘要: 题目大意:给N个数(N不超过200000), 保证第一个数比后面的都大, 要求你把数列分成连续的三段, 分别逆序再拼起来, 要求新的串字典序最小.简要分析:一个直接的思路是想把最小的一个数作为第一段的末尾, 这样是不是最优的呢? 是的, 因为第一个数比后面的数都大, 于是你把所有的最小的数作为第一段的末尾逆序时, 最大的数之前的部分的字典序肯定不一样. 于是就先把整个序列逆序, 求一个后缀数组, 按i从小到大考虑sa[i], 因为第一个串的长度最多是N - 2, 所以sa[i]必须大于2, 找到最小的i即可.于是问题转化为, 一个数字串, 分成两段并分别逆序, 使得字典序最小. 假设序列为s, 阅读全文
posted @ 2012-03-10 19:37 zcwwzdjn 阅读(811) 评论(0) 推荐(0) 编辑