SPOJ1811-LCS-后缀自动机
题目描述
题解
首先对
A
A
A串建立一个后缀自动机,然后让
B
B
B串一个一个字符去匹配;
匹配方式:
首先置
l
e
n
=
0
len=0
len=0,然后从根节点开始遍历下去
1,如果当前节点存在,就
l
e
n
+
+
len++
len++,继续遍历下一个节点
2,如果当前节点不存在,就跳该节点的
f
a
fa
fa,
2.1,如果跳的过程中找到了该节点,那么就继续从该节点遍历下去,
l
e
n
len
len置为当前节点的长度
+
1
+1
+1(因为某个节点的
f
a
fa
fa一定是该节点的后缀,因此有正确性)
2.2,如果没有找到,就重新从根节点开始遍历,置
l
e
n
len
len为0
3,更新答案
代码
#include<bits/stdc++.h>//SAM
#define M 250009
using namespace std;
struct sam{
int ch[26],fa,len;
}tr[M*2];
int n,m,last,rt,ans,cnt;
char s1[M],s2[M];
void extend(int pos){
int np=++cnt,val=s1[pos]-'a',p=last;
tr[np].len=pos,last=np;
while(p&&!tr[p].ch[val]) tr[p].ch[val]=np,p=tr[p].fa;
if(!p) tr[np].fa=rt;
else{
int q=tr[p].ch[val];
if(tr[q].len==tr[p].len+1) tr[np].fa=q;
else{
int nq=++cnt;
tr[nq].len=tr[p].len+1;
memcpy(tr[nq].ch,tr[q].ch,sizeof(tr[q].ch));
tr[nq].fa=tr[q].fa,tr[q].fa=tr[np].fa=nq;
while(p&&tr[p].ch[val]==q) tr[p].ch[val]=nq,p=tr[p].fa;
}
}
}
int getans(){
int p=rt,len=0;
for(int i=1;i<=m;i++){
int val=s2[i]-'a';
if(tr[p].ch[val]) len++,p=tr[p].ch[val];
else{
while(p&&!tr[p].ch[val]) p=tr[p].fa;
if(!p) len=0,p=rt;
else len=tr[p].len+1,p=tr[p].ch[val];
}ans=max(ans,len);
}return ans;
}
int main(){
scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1),m=strlen(s2+1);
last=rt=++cnt;
for(int i=1;i<=n;i++) extend(i);
printf("%d\n",getans());
return 0;
}
后记
后缀自动机学习笔记推荐网站:https://oi-wiki.org/string/sam/