第三场春训,谢谢lyt学长 qwq!
(在肝数分没有去QAQ,要好好补题)
【BUAA Spring Training 03】
Tags:字符串哈希 FFT Manacher Trie AC自动机
Problem A. Prefixes and Suffixes
[A] 题意
给定一个小写字母字符串 s s s( 1 ≤ ∣ s ∣ ≤ 1 0 5 1 \le |s| \le 10^5 1≤∣s∣≤105),求它的每一个匹配的相同前后缀的长度,及其在 s s s 中的出现次数(按长度升序输出答案)。
[A] 思路
签到题,next 数组的经典应用:找所有的相同前后缀。
从 next \text{next} next 数组最后一位不断回滚即可找到所有相同前后缀(可以拿栈存一下,这样刚好就能按长度升序输出了)
接下来要求每个串的出现次数。显然那些长度小的都是长度大的的前缀/后缀,所以每次长度大的出现一次则会让长度小的再出现一次。利用 next 数组的性质,我们倒着扫一遍(就相当于遍历 s s s 的每一个前缀了),先让它自己的次数++,然后如果它包含了某个小的就让这个小的次数+=它的次数,然后就得到答案了。
时间复杂度: O ( ∣ s ∣ ) O(|s|) O(∣s∣)
[A] 代码
#include <cstdio>
#include <cstring>
constexpr int ML(1e5+6);
char s[ML];
int next[ML];
int get_next()
{
int i = 0, j = next[0] = -1, len = strlen(s);
while (i < len)
{
if (j==-1 || s[i]==s[j])
next[++i] = ++j;
else
j = next[j];
}
return len;
}
int dp[ML];
int sta[ML], top;
int main()
{
scanf("%s", s);
int len = get_next();
for (int i=len; i; i=next[i])
sta[top++] = i;
for (int i=len; i; i--)
++dp[i], dp[next[i]] += dp[i];
printf("%d\n", top);
while (top--)
printf("%d %d\n", sta[top], dp[sta[top]]);
return 0;
}
Problem B. Watto and Mechanism
(待更)