忍耐,也是一件美好的事,但前提是你有非常清晰的未来版图,你知道忍耐这一段后,会有什么等着你,你愿意为此暂时收起自己的羽毛。
「一本通 2.4 练习 1」玄武密码
题目描述
原题来自:JSOI 2012
在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此。
很多年后,人们终于在进香河地区发现了带有玄武密码的文字。更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联。于是,漫长的破译工作开始了。
经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为 NN 的序列来描述,序列中的元素分别是 E
,S
,W
,N
,代表了东南西北四向,我们称之为母串。而神秘的玄武密码是由四象的图案描述而成的 M 段文字。这里的四象,分别是东之青龙,西之白虎,南之朱雀,北之玄武,对东南西北四向相对应。
现在,考古工作者遇到了一个难题。对于每一段文字,其前缀在母串上的最大匹配长度是多少呢?
输入格式
第一行有两个整数,N 和 M,分别表示母串的长度和文字段的个数;
第二行是一个长度为 N 的字符串,所有字符都满足是 E
,S
,W
和 N
中的一个;
之后 M 行,每行有一个字符串,描述了一段带有玄武密码的文字。依然满足,所有字符都满足是 E
,S
,W
和 N
中的一个。
输出格式
输出有 MM 行,对应 MM 段文字。
每一行输出一个数,表示这一段文字的前缀与母串的最大匹配串长度。
样例
样例输入
1 | 7 3 |
样例输出
1 | 4 |
数据范围与提示
对于全部数据,
,保证每一段文字的长度均小于等于 100。
题解
还是比较简单的一道AC自动机 + DP(调了3个小时)
本来我想直接写个普通的不带Trie图优化的AC自动机然后直接在Trie树上DP,结果惊讶的发现写错了,还调不出来,甚至怀疑自己学了假的AC自动机。
既然这样就在保留一颗没有变成Trie图的Trie树用来DP就好了。
我们在Trie树上进行AC自动机匹配,由AC自动机原理可知所有访问过的编号大于1的点都是能够在原串上匹配到的字符串,我们把这些点都标记一下。
接下来应该让每个模式串结尾的Trie上节点都向上跳到最深被标记的节点,显然不能暴力跳。
那就从根节点向下递推就好了,设
表示节点k跳到的深度最大的标记点。对于被标记的点,
没被标记的
但是要注意,模式串有重复!!各种调试最终找到了这个错误。
所以标记要用vector存。
时间复杂度显然是
Code:
1 |
|
终于把不带任何优化,完全按照原理匹配的AC自动机调出来了。。。仅仅是因为一个很sb的匹配的错误:
AC:
1 | inline void find(char* s) |
WA:
1 | inline void find(char* s) |
显然在u转移之后才能统计啊。。不然第一个字符永远没法匹配当然挂了。
以后把bug代码贴出来似乎是个不错的主意。
话说更令人惊奇的是,不带优化的AC自动机比Trie图快了整整两秒。。。怕不是逆优化。
完整的按原理的AC自动机
Code:
1 |
|
「一本通 2.4 练习 2」Censoring
题目描述
原题来自:USACO 2015 Feb. Gold
有一个长度不超过 10^5105 的字符串 SS。Farmer John 希望在 SS 中删掉 nn 个屏蔽词(一个屏蔽词可能出现多次),这些词记为 t_1\sim t_nt1∼tn。
FJ 在 S 中从头开始寻找屏蔽词,一旦找到一个屏蔽词,FJ 就删除它,然后又从头开始寻找(而不是接着往下找)。FJ 会重复这一过程,直到 S 中没有屏蔽词为止。注意删除一个单词后可能会导致 S 中出现另一个屏蔽词。这 n 个屏蔽词不会出现一个单词是另一个单词子串的情况,这意味着每个屏蔽词在 S 中出现的开始位置是互不相同的,请帮助 FJ 完成这些操作并输出最后的 S。
输入格式
第一行包含一个字符串 S;
第二行包含一个整数 n;
接下来的 n 行,每行包含一个字符串,第 ii 行的字符串是 t_i。
输出格式
一行,输出操作后的 SS。保证 SS 不会变成空串。
样例
样例输入
1 | begintheescapexecutionatthebreakofdawn |
样例输出
1 | beginthatthebreakofdawn |
数据范围与提示
对于全部数据,
保证所有字符串只出现小写字母。
题解
感觉有点想法。
首先对模式串建立不带Trie图优化的AC自动机(以后再也不想写Trie图优化了)。。。
然后开始对母串匹配(母串一定要读一个字符串方便操作!qwq)
我们在匹配的时候记录母串当前点u匹配到的自动机上的点
,然后假如下一位匹配到了模式串我们用字符串函数将其删除,然后回跳指针至这个单词前一位,令匹配指针u指 向$g(u)$,继续完成匹配,和普通AC自动机匹配复杂度相同(每个点最多被访问和删除一次),为
结果写炸了,以后补代码(咕咕咕)吧。
斜率优化DP
先看一道题
「一本通 5.6 例 1」任务安排 1
题目描述
原题来自:JoyOI TYVJ 1098
有 NN 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。机器会把这 NN 个任务分成若干批,每一批包含连续的若干个任务。从时刻 00 开始,任务被分批加工,执行第i个任务所需的时间是 T_iTi。另外,在每批任务开始前,机器需要 SS 的启动时间,故执行一批任务所需的时间是启动时间 SS 加上每个任务所需时间之和。
一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。也就是说,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数 C_iCi。
请为机器规划一个分组方案,使得总费用最小。
输入格式
第一行是 N。第二行是 S。
下面 NN 行每行有一对正整数,分别为 T_i和 C_i,表示 ii 个任务单独完成所需的时间是 T_i及其费用系数 C_iCi。
输出格式
一个数,最小的总费用。
样例
样例输入
1 | 5 |
样例输出
1 | 153 |
样例说明
分组方案为 \{1,2\},\{3\},\{4,5\}则完成时间为 \{5,5,10,14,14\}费用 C=\{15,10,30,42,56\}总费用为 153。
数据范围与提示
对于全部数据
题解
很容易就想到一个
的做法
设
表示前n个任务分p段完成,枚举最后一段人数转移
Code:
1 |
|
这时有这样一种思想非常重要,在以前的贪心算法中也曾应用(比如种树),就是费用提前计算的思想。
我们设f(k)表示前k项分成若干段的最小费用。
枚举最后的一段转移。
让我再体会一下这种神奇的思想。
时间复杂度
Code:
1 |
|