码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ LCS2 - Longest Common Substring II 字符串 SAM

时间:2018-05-02 22:14:49      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:匹配   cpp   const   blog   ace   dong   字符   bit   最大匹配   

原文链接http://www.cnblogs.com/zhouzhendong/p/8982484.html

题目传送门 - SPOJ LCS2

题意

  求若干$(若干<10)$个字符串的最长公共连续子串长度。

  串长$\leq 100000$

题解

  建议在做本题之前,先去做SPOJ LCS,本题是其升级版。

  题解链接 - SPOJ LCS - http://www.cnblogs.com/zhouzhendong/p/8982392.html

  对于本题,我们只需要保持一下之后每一个串在第一个串的$SAM$的每一个状态上的最大匹配长度,然后最后对于每一个状态,取$min(该状态的Max值,其他所有字符串在该状态上面的最大匹配长度的最小值)$即可。

  于是,我们先像SPOJ LCS一样,让所有串都走一遍,然后记录一下值。

  注意到,每一个状态的结果都会对其$fa$做贡献。

  于是我们可以基数排序预处理拓扑序,然后逆序更新即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=200005;
int n,m=0,last=1,size=1,Max[15][N];
int id[N],tax[N];
char s[N];
struct SAM{
	int Next[26],fa,Max;
}t[N];
void expend(int c){
	int p=last,np=++size,q,nq;
	t[np].Max=t[p].Max+1;
	for (;!t[p].Next[c];p=t[p].fa)
		t[p].Next[c]=np;
	q=t[p].Next[c];
	if (t[q].Max==t[p].Max+1)
		t[np].fa=q;
	else {
		nq=++size;
		t[nq]=t[q],t[nq].Max=t[p].Max+1;
		t[q].fa=t[np].fa=nq;
		for (;t[p].Next[c]==q;p=t[p].fa)
			t[p].Next[c]=nq;
	}
	last=np;
}
int main(){
	t[0].Max=-1;
	for (int i=0;i<26;i++)
		t[0].Next[i]=1;
	gets(s);
	n=strlen(s);
	for (int i=0;i<n;i++)
		expend(s[i]-‘a‘);
	for (int i=1;i<=size;i++)
		tax[t[i].Max]++;
	for (int i=1;i<=size;i++)
		tax[i]+=tax[i-1];
	for (int i=1;i<=size;i++)
		id[tax[t[i].Max]--]=i;
	while (gets(s)&&strlen(s)){
		n=strlen(s);
		for (int i=0,now=1,len=0;i<n;i++){
			int c=s[i]-‘a‘;
			if (t[now].Next[c]){
				len++;
				now=t[now].Next[c];
				Max[m][now]=max(Max[m][now],len);
				continue;
			}
			while (!t[now].Next[c])
				now=t[now].fa;
			len=t[now].Max+1;
			now=t[now].Next[c];
			Max[m][now]=max(Max[m][now],len);
		}
		for (int i=size;i>=1;i--)
			Max[m][t[id[i]].fa]=max(Max[m][t[id[i]].fa],Max[m][id[i]]);
		m++;
	}
	int ans=0;
	for (int i=1;i<=size;i++){
		int now=t[i].Max;
		for (int j=0;j<m;j++)
			now=min(now,Max[j][i]);
		ans=max(ans,now);
	}
	printf("%d",ans);
	return 0;
}

  

SPOJ LCS2 - Longest Common Substring II 字符串 SAM

标签:匹配   cpp   const   blog   ace   dong   字符   bit   最大匹配   

原文地址:https://www.cnblogs.com/zhouzhendong/p/8982484.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!