SPOJ LCS2 - Longest Common Substring II 字符串 SAM
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ LCS2 - Longest Common Substring II 字符串 SAM相关的知识,希望对你有一定的参考价值。
原文链接http://www.cnblogs.com/zhouzhendong/p/8982484.html
题目传送门 - SPOJ LCS2
题意
求若干$(若干<10)$个字符串的最长公共连续子串长度。
串长$\\leq 100000$
题解
建议在做本题之前,先去做SPOJ LCS,本题是其升级版。
题解链接 - SPOJ LCS - http://www.cnblogs.com/zhouzhendong/p/8982392.html
对于本题,我们只需要保持一下之后每一个串在第一个串的$SAM$的每一个状态上的最大匹配长度,然后最后对于每一个状态,取$min(该状态的Max值,其他所有字符串在该状态上面的最大匹配长度的最小值)$即可。
于是,我们先像SPOJ LCS一样,让所有串都走一遍,然后记录一下值。
注意到,每一个状态的结果都会对其$fa$做贡献。
于是我们可以基数排序预处理拓扑序,然后逆序更新即可。
代码
#include <bits/stdc++.h> using namespace std; const int N=200005; int n,m=0,last=1,size=1,Max[15][N]; int id[N],tax[N]; char s[N]; struct SAM{ int Next[26],fa,Max; }t[N]; void expend(int c){ int p=last,np=++size,q,nq; t[np].Max=t[p].Max+1; for (;!t[p].Next[c];p=t[p].fa) t[p].Next[c]=np; q=t[p].Next[c]; if (t[q].Max==t[p].Max+1) t[np].fa=q; else { nq=++size; t[nq]=t[q],t[nq].Max=t[p].Max+1; t[q].fa=t[np].fa=nq; for (;t[p].Next[c]==q;p=t[p].fa) t[p].Next[c]=nq; } last=np; } int main(){ t[0].Max=-1; for (int i=0;i<26;i++) t[0].Next[i]=1; gets(s); n=strlen(s); for (int i=0;i<n;i++) expend(s[i]-\'a\'); for (int i=1;i<=size;i++) tax[t[i].Max]++; for (int i=1;i<=size;i++) tax[i]+=tax[i-1]; for (int i=1;i<=size;i++) id[tax[t[i].Max]--]=i; while (gets(s)&&strlen(s)){ n=strlen(s); for (int i=0,now=1,len=0;i<n;i++){ int c=s[i]-\'a\'; if (t[now].Next[c]){ len++; now=t[now].Next[c]; Max[m][now]=max(Max[m][now],len); continue; } while (!t[now].Next[c]) now=t[now].fa; len=t[now].Max+1; now=t[now].Next[c]; Max[m][now]=max(Max[m][now],len); } for (int i=size;i>=1;i--) Max[m][t[id[i]].fa]=max(Max[m][t[id[i]].fa],Max[m][id[i]]); m++; } int ans=0; for (int i=1;i<=size;i++){ int now=t[i].Max; for (int j=0;j<m;j++) now=min(now,Max[j][i]); ans=max(ans,now); } printf("%d",ans); return 0; }
UPD(2018-05-07):
听说有人要用hash过这题??
看这个:
来自陈立杰的后缀自动机课件
以上是关于SPOJ LCS2 - Longest Common Substring II 字符串 SAM的主要内容,如果未能解决你的问题,请参考以下文章
刷题SPOJ 1812 LCS2 - Longest Common Substring II
spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)
●SPOJ LCS2Longest Common Substring II
SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS