[CF427D] Match & Catch

\(\text{Problem}:\)Match & Catch

\(\text{Solution}:\)

对第一个串 \(S1\) 建出 \(\text{SAM}\),第二个串 \(S2\) 去匹配。设当前匹配到的状态为 \(x\),最长长度为 \(now\)。如果在 \(\text{parent}\) 树上 \(x\) 不是叶子节点,则 \(S1\) 在状态 \(x\) 上的子串出现次数大于 \(1\),不满足条件;否则,对右端点 \(i\)\(S1\) 满足条件的子串的长度区间为 \([\text{len(link}(x))+1,now]\)

再对 \(S2\) 建出 \(\text{SAM}\),用 \(S2\) 去匹配。易知对于每个右端点 \(i\),状态 \(x\) 都对应了 \(S2\) 的一段前缀,所以 \(S2\) 满足条件的子串的长度区间为 \([\text{len(link}(x))+1,i]\)。发现对于每个右端点 \(i\)\(S1\)\(S2\) 分别有一段满足条件的长度区间,取交集后即可求解。

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=10010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
char s[N],t[N];
int n,m,F[N],leaf[N],G[N];
struct SAM
{
	int link[N],len[N],ch[N][26];
	int tot,lst;
	inline SAM() { tot=lst=1; link[1]=len[1]=0; memset(ch[1],0,sizeof(ch[1])); }
	inline void Extend(int c)
	{
		int now=++tot;
		int p=lst;
		while(p && !ch[p][c]) ch[p][c]=now, p=link[p];
		len[now]=len[lst]+1;
		if(!p) { lst=now, link[now]=1; return; }
		int q=ch[p][c];
		if(len[q]==len[p]+1) link[now]=q;
		else
		{
			int nq=++tot;
			len[nq]=len[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			link[nq]=link[q];
			link[q]=link[now]=nq;
			while(p && ch[p][c]==q) ch[p][c]=nq, p=link[p];
		}
		lst=now;
	}
	inline void Renew()
	{
		for(ri int i=1;i<=tot;i++) link[i]=len[i]=leaf[i]=0, memset(ch[i],0,sizeof(ch[i]));
		tot=lst=1;
	}
}A;
signed main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	scanf("%s",t+1);
	m=strlen(t+1);
	for(ri int i=1;i<=n;i++) A.Extend(s[i]-'a');
	for(ri int i=2;i<=A.tot;i++) leaf[A.link[i]]=1;
	int sta=1, now=0;
	for(ri int i=1;i<=m;i++)
	{
		int p=t[i]-'a';
		while(sta && !A.ch[sta][p]) sta=A.link[sta], now=A.len[sta];
		if(!sta) sta=1;
		if(A.ch[sta][p]) sta=A.ch[sta][p], now++;
		if(!leaf[sta]) F[i]=A.len[A.link[sta]]+1, G[i]=now;
		else F[i]=G[i]=1e9;
	}
	A.Renew();
	for(ri int i=1;i<=m;i++) A.Extend(t[i]-'a');
	for(ri int i=2;i<=A.tot;i++) leaf[A.link[i]]=1;
	sta=1; int ans=1e9;
	for(ri int i=1;i<=m;i++)
	{
		int p=t[i]-'a';
		sta=A.ch[sta][p];
		int L=A.len[A.link[sta]]+1, R=A.len[sta];
		if(leaf[sta] || min(G[i],R)<max(F[i],L) || F[i]==1e9 || G[i]==1e9) continue;
		else ans=min(ans,max(F[i],L));
	}
	printf("%d\n",(ans>=1e9)?(-1):ans);
	return 0;
}
posted @ 2021-03-29 18:08  zkdxl  阅读(57)  评论(0编辑  收藏  举报