SP1811 LCS - Longest Common Substring(SAM)

SP1811 LCS - Longest Common Substring(SAM)

思路:

1.对第一个字符串建立 S A M SAM ,然后第二个字符串在 S A M SAM 跑,有转移就 a n s + + ans++ ,然后 p p 变为他的转移结点,否则跳 f a i l fail ,若跳到 0 0 a n s = 0 , p = 1 ans=0,p=1 ,否则更新 a n s = l e n [ p ] + 1 , p = c h [ p ] [ x ] ans=len[p]+1,p=ch[p][x]

2.广义 S A M SAM ,用 l a s t = 1 last=1 实现,然后将 f a i l [ i ] , i fail[i],i 连边建图,跑 S A M SAM 的时候储存在每个状态在对应的字符串是否出现过 s z [ n p ] [ o p ] , o p { 0 , 1 } sz[np][op],op\in\{0,1\}

然后在图上跑 d f s dfs ,取最值。

时间复杂度: O ( Σ n ) O(|\Sigma| n)

做法1:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define IOS ios::sync_with_stdio(false),cin.tie(0)
int n,q; 
char a[N],b[N];
struct SAM{
	int last,cnt;int ch[N<<1][26],fa[N<<1],len[N<<1];
	void insert(int c){
		int p=last,np=++cnt;last=np;len[np]=len[p]+1;
		for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
		if(!p) fa[np]=1;
		else {
			int q=ch[p][c];
			if(len[q]==len[p]+1) fa[np]=q;
			else  {
				int nq=++cnt;len[nq]=len[p]+1;
				memcpy(ch[nq],ch[q],sizeof ch[q]);
				fa[nq]=fa[q],fa[q]=fa[np]=nq;
				for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
			}
		}
	}
	void build(){
		last=cnt=1;
		scanf("%s",a+1);
		for(int i=1;a[i];i++)
			insert(a[i]-'a');
		scanf("%s",b+1);
		int ans=0,p=1,res=0;
		for(int i=1;b[i];i++){
			int x=b[i]-'a';
			if(ch[p][x]) p=ch[p][x],ans++;
			else {
				while(p&&!ch[p][x]) p=fa[p];
				if(!p) p=1,ans=0;
				else ans=len[p]+1,p=ch[p][x];
			}
			if(res<ans) res=ans;
		}
		printf("%d\n",res);
	}
}sam;
int main(){
	IOS;
	sam.build();
	return 0;
}

做法2:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define IOS ios::sync_with_stdio(false),cin.tie(0)
int n,q,tot; 
char a[N],b[N];
struct SAM{
	int last,cnt;int ch[N<<1][26],fa[N<<1],len[N<<1];
	int to[N<<1],nt[N<<1],h[N<<1],ans=0;
	void add(int u,int v){
		to[++tot]=v,nt[tot]=h[u],h[u]=tot;
	}
	bool sz[N<<1][2];
	void insert(int c,int op){
		int p=last,np=++cnt;last=np;len[np]=len[p]+1;
		sz[np][op]=true; 
		for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
		if(!p) fa[np]=1;
		else {
			int q=ch[p][c];
			if(len[q]==len[p]+1) fa[np]=q;
			else  {
				int nq=++cnt;len[nq]=len[p]+1;
				memcpy(ch[nq],ch[q],sizeof ch[q]);
				fa[nq]=fa[q],fa[q]=fa[np]=nq;
				for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
			}
		}
	}
	void build(){
		last=cnt=1;
		scanf("%s",a+1);
		for(int i=1;a[i];i++)
			insert(a[i]-'a',0);
		last=1;
		scanf("%s",b+1);
		for(int i=1;b[i];i++)
			insert(b[i]-'a',1);
		for(int i=2;i<=cnt;i++) add(fa[i],i);
	}
	void dfs(int u){
		for(int i=h[u];i;i=nt[i]){
			 dfs(to[i]);
			 int v=to[i];
			 sz[u][0]|=sz[v][0],sz[u][1]|=sz[v][1];
		}
		if(sz[u][0]&&sz[u][1]) ans=max(ans,len[u]);
	}
}sam;
int main(){
	IOS;
	sam.build();
	sam.dfs(1);
	printf("%d\n",sam.ans); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107503768