【题解】SP10570 【LONGCS - Longest Common Substring】

\(\color{Red}{Link}\)

\(\text{Solution:}\)

还是\(\text{Suffix Tree.}\)

根据\(\color{Blue}{Link}\)我们可以得到一个普适性较强的做法。

而这题就是多组数据。改下数据即可。

但是字符串的输入要绝对注意,每一次的清空都不能落下。

#include<bits/stdc++.h>
#include<ctime>
using namespace std;
const int MAXN=2e6+10;
char Z[20][100001];
int n,val[MAXN],ans,M,num,Case;
int sum[20][MAXN];
const int inf=(1<<30);
struct SuffixTree {
	int link[MAXN],ch[MAXN][50],now,rem,n;
	int start[MAXN],len[MAXN],tail,s[MAXN];
	SuffixTree() {
		tail=now=1;
		rem=n=0;
		len[0]=inf;
	}
	inline int build(int a,int b) {
		link[++tail]=1;
		start[tail]=a;
		len[tail]=b;
		return tail;
	}
	void Extend(int x) {
		s[++n]=x;
		++rem;
		for(int last=1; rem;) {
			while(rem>len[ch[now][s[n-rem+1]]])
				rem-=len[now=ch[now][s[n-rem+1]]];
			int &v=ch[now][s[n-rem+1]];
			int c=s[start[v]+rem-1];
			if(!v||x==c) {
				link[last]=now;
				last=now;
				if(!v)v=build(n,inf);
				else break;
			} else {
				int u=build(start[v],rem-1);
				ch[u][c]=v;
				ch[u][x]=build(n,inf);
				start[v]+=rem-1;
				len[v]-=rem-1;
				link[last]=v=u;
				last=u;
			}
			if(now==1)--rem;
			else now=link[now];
		}
	}
	void clear(){
		memset(start,0,sizeof(start));
		memset(len,0,sizeof(len));
		memset(ch,0,sizeof(ch));
		memset(link,0,sizeof(link));
		memset(s,0,sizeof(s));
		tail=now=1;rem=n=0;len[0]=inf;
	}
} T;
void predfs(int u,int dep) {
	if(dep>=inf) {
		int L=T.start[u];
		int R=L+T.len[u]-1;
		R=min(R,T.n);
		for(int i=1; i<=num; ++i) {
			if(sum[i][R]-sum[i][L-1]) {
				val[u]|=(1<<i);
				break;
			}
		}
		return;
	}
	for(int i=0; i<=25+num; ++i) {
		if(T.ch[u][i]) {
			predfs(T.ch[u][i],dep+T.len[T.ch[u][i]]);
			val[u]|=val[T.ch[u][i]];
		}
	}
	if(val[u]==M)ans=max(ans,dep);
}
inline void print(char* x){
	for(int i=1;i<=strlen(x+1);++i)cout<<x[i];
	cout<<endl;
}
int main() {
	scanf("%d",&Case);
	//cout<<M<<endl;
	while(Case--) {
		scanf("%d",&num);ans=0;M=0;
		for(int i=1;i<=num;++i)scanf("%s",Z[i]+1);
		int G='0';
		int len=strlen(Z[1]+1);
		Z[1][++len]=(char)G;
		for(int i=2; i<=num; ++i) {
			G++;
			int L=strlen(Z[i]+1);
			for(int j=1; j<=L; ++j)Z[1][++len]=Z[i][j];
			Z[1][++len]=(char)G;
		}
		for(int i=1; i<=num; ++i)M+=(1<<i);
		for(int i=1; i<=len; ++i) {
			if(Z[1][i]>='a')T.Extend(Z[1][i]-'a');
			else T.Extend(Z[1][i]-'0'+1+25);
		}
		for(int i=1; i<=len; ++i) {
			for(int j=1; j<=num; ++j)sum[j][i]=sum[j][i-1];
			if(T.s[i]>25) {
				int V=T.s[i]-25;
				sum[V][i]++;
			}
		}
		predfs(1,0);
		cout<<ans<<endl;
		T.clear();
		memset(val,0,sizeof(val));
		memset(sum,0,sizeof(sum));
		//print(Z[1]);
	}
	return 0;
}
posted @ 2020-06-26 14:14  Refined_heart  阅读(133)  评论(0编辑  收藏  举报