SPOJ1811-LCS-后缀自动机

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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值