SAM详解3.2(关于2和3的题)
SAM
- SAM
- luogu6640
- 分析
- 优化
- CF653F
- 分析
- 维护
SAM
推销一波前面的文章:
SAM详解1
SAM详解2(初级应用)
SAM详解3(SAM与AC自动机的相似性,SAM处理字符串匹配)
luogu6640
题目链接
给出只包含小写字母 a
和 b
的两个字符串 s , t s,t s,t, q q q 次询问,每次询问 s [ l … r ] s[l…r] s[l…r] 和 t t t 的最长公共子串长度。
分析
看到最长公共子串,建出 t t t 的 SAM,然后让 s s s 在上面跑匹配,记跑出来的数组是 s l e n slen slen。
然后可以看出答案:
a n s = max i = l r min ( i − l + 1 , s l e n [ i ] ) ans=\max_{i=l}^r\min(i-l+1,slen[i]) ans=i=lmaxrmin(i−l+1,slen[i])
于是有了暴力 O ( q n ) O(qn) O(qn) 的做法。
优化
发现括号内的 min \min min 不好维护,考虑拆括号。
当 i − l + 1 < s l e n [ i ] i-l+1<slen[i] i−l+1<slen[i] 时,有 i − s l e n [ i ] + 1 < l i-slen[i]+1<l i−slen[i]+1<l
然后有个性质 i − s l e n [ i ] + 1 i-slen[i]+1 i−slen[i]+1 单调不降。
证明:
回顾 s l e n slen slen 的计算过程:
for(int i=1,p=1,L=0;i<=n;i++){while(p&&!a[p].ch[s1[i]-'a']){p=a[p].f;L=a[p].len;}if(!p)p=1;elsep=a[p].ch[s1[i]-'a'],L++;slen[i]=L;}
L L L 每次最多增加 1 1 1,或者减少。
而 i i i 每次稳定增加 1 1 1。
得证。
于是可以用二分求出一个