您的位置:首页 > 其它

SPOJ LCS2 Longest Common Substring II + BZOJ 2946 [Poi2000]公共串

2018-02-24 11:40 232 查看
A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

Input

The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn’t exist, print “0” instead.

Example

Input:

alsdfkjfjkdsal

fdjskalajfkdsla

aaaajfaaaa

Output:

2

Notice:

new testcases added

思路

BZOJ是权限题,不放题目描述了;

其实这两道题是双倍经验题;

对第一个串建SAM,把后面的串放在这个SAM上跑,记录到达一个节点这一个串的最长的长度,到达一个点需要把它的parent树上的祖先全部更新一遍,对每个记录所有串的最小值,这些节点记录的值的最大值就是答案。

ans=max(节点的答案=min(串到达这个节点的最长长度=max(串到达这个节点的长度)))


代码

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn=250000;
const int maxk=500000;

struct node
{
node* tr[26];
node* par;
int maxl,num;
};

struct suffix_automaton
{
node* qs;
node* qlast;
node samnode[maxk+10];
int cnt,tmp[maxk+10],ans[maxk+10],ki[maxk+10];

inline int clear()
{
delete qs;
delete qlast;
qlast=qs=new node();
cnt=0;
return 0;
}

inline int addchr(int ch)
{
node* p=qlast;
node* np=&samnode[++cnt];
np->maxl=qlast->maxl+1;
qlast=np;
np->num=cnt;
while((p!=NULL)&&(p->tr[ch]==NULL))
{
p->tr[ch]=np;
p=p->par;
}
if(p==NULL)
{
np->par=qs;
return 0;
}
node* q=p->tr[ch];
if(q->maxl!=p->maxl+1)
{
node* nq=&samnode[++cnt];
nq->maxl=p->maxl+1;
nq->num=cnt;
memcpy(nq->tr,q->tr,sizeof q->tr);
nq->par=q->par;
q->par=np->par=nq;
while((p!=NULL)&&(p->tr[ch]==q))
{
p->tr[ch]=nq;
p=p->par;
}
}
else
{
np->par=q;
}
return 0;
}

inline int sortmaxl()
{
for(register int i=1; i<=cnt; ++i)
{
ans[i]=samnode[i].maxl;
}
for(register int i=1; i<=cnt; ++i)
{
++tmp[samnode[i].maxl];
}
for(register int i=2; i<=cnt; ++i)
{
tmp[i]+=tmp[i-1];
}
for(register int i=cnt; i; --i)
{
ki[tmp[samnode[i].maxl]--]=i;
}
return 0;
}

inline int run(char* s,int len)
{
node* q=qs;
int l=0;
memset(tmp,0,sizeof tmp);
for(register int i=1; i<=len; ++i)
{
int ch=s[i]-'a';
while((q!=NULL)&&(q->tr[ch]==NULL))
{
q=q->par;
}
if(q==NULL)
{
q=qs;
l=0;
}
else
{
l=std::min(l,q->maxl)+1;
q=q->tr[ch];
}
tmp[q->num]=std::max(tmp[q->num],l);
}
for(register int i=cnt; i; --i)
{
tmp[samnode[ki[i]].par->num]=std::max(tmp[samnode[ki[i]].par->num],tmp[ki[i]]);
}
for(register int i=1; i<=cnt; ++i)
{
ans[i]=std::min(ans[i],tmp[i]);
}
return 0;
}

inline int lcs()
{
int a=0;
for(register int i=1; i<=cnt; ++i)
{
a=std::max(a,ans[i]);
}
return a;
}
};

suffix_automaton sam;
char s[maxn+10];

int main()
{
scanf("%s",s+1);
int len=strlen(s+1);
sam.clear();
for(register int i=1; i<=len; ++i)
{
sam.addchr(s[i]-'a');
}
sam.sortmaxl();
while(~scanf("%s",s+1))
{
sam.run(s,strlen(s+1));
}
printf("%d\n",sam.lcs());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: