CUGBACM18 级训练#3 题解

1.HDU1686 #

题意: 给出两个串 S1,S2S_1,S_2,问S1S_1S2S_2中出现的次数。

思路: kmp 板子题,注意要用 scanf。


2.HDU2594 #

题意: 给出两个字符串S1,S2S_1,S_2,求最长的既是S1S_1前缀又是S2S_2后缀的字符串。

思路: 很明显就是把两个串拼起来然后求前缀函数,不过要注意的是拼起来的串的前缀函数有可能超过给出的串的长度,解决办法就是在两个串中间加一个符号。


3.HDU6629 #

题意: 给出字符串SS问用暴力算法求SS的 Z 函数(一个长度为 n 的数组,其中第 i 个元素为满足从位置 i 开始且为 s 前缀的字符串的最大长度。)需要的比较次数。

思路: 求每一个位置的比较次数都等于这个位置的 z 函数 +1,因为要往后面多比较一次发现不匹配了才会终止(如果比较到字符串末尾了即 i+z[i]>=n 就不用加 1),求和就是答案。


4.Codeforces 1200E #

题意: 给了你 n 个字符串,然后按照如下方式合并得到新串SS':

  1. 如果SS'为空串,则直接加入SS'
  2. 否则,每次比较SS'的后缀与前缀,取失配位置之后的后缀加入SS'

求 s′

思路: 设答案串的长度为LansL_{ans},需要合并的新串的长度为LL,将“新串+#+答案串后面长min(Lans,L)\min(L_{ans},L)的子串”作为整体跑前缀函数,设整个串的最长公共前后缀的长度为lenlen,将新串下标为len,len+1,,L1len,len+1, \cdots,L-1的子串加到答案串之后。


5.HDU3613 #

题意: 给出一字符串,其中每一种字符对应一个价值,将字符串切成两段,计算两段的价值和,方法如下:如果这一段是回文串,价值就是每一个字符对应的价值的和,否则该串价值为 0。求两段价值之和的最大值。

思路: 先跑一遍大可马拉车算法,然后遍历求出串的价值前缀和,然后枚举分割点,找到两个串的中心,判断中心的回文串是不是整个串,如果是就利用之前算的前缀和加那个串的价值,在枚举中不断更新答案即可。


6. HDU2222 #

题意:给出 n 个单词和一个长串,问有几个单词在长串中出现过。

思路:AC 自动机板子题,好像没什么好说的……


7.HDU2896 #

题意: 给出 n 个单词(病毒)和 m 个长串(源码)问每个长串中有哪些单词出现过以及有多少个源码中有病毒。

思路: 和上个题类似,字符集不只是 26 个字母了……是所有 ASCII 可见字符,不过开到 130 就行,不用统计出现次数,新加一个数组记录病毒编号在字典树上的位置,查询的时候如果某个节点对应的病毒编号不为 0 就加入答案数组,排序之后输出,如果答案数组的大小不为 0,总个数加 1,最后输出总个数。