-----------------
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 simple, for two 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 exactly two lines, each line consists of no more than 250000 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 Output: 3
-----------------
SAM用O(n)跑LCS
-----------------
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define sz(x) int(x.size())
using namespace std;
typedef vector<int> VI;
const int maxn = 250000+10;
class SuffixAutomaton{
private:
struct Node{
Node *suf, *go[26];
int val;
Node(){
suf=NULL;
val=0;
memset(go,0,sizeof(go));
}
void clear(){
suf=NULL;
val=0;
memset(go,0,sizeof(go));
}
int calc(){
if (suf==0) return 0;
return val-suf->val;
}
};
Node *root,*last;
Node nodePool[maxn*2],*cur;
Node* newNode(){
Node* res=cur++;
res->clear();
return res;
}
int tot;
void extend(int w){
Node *p=last;
Node *np=newNode();
np->val=p->val+1;
while (p&&!p->go[w]){
p->go[w]=np;
p=p->suf;
}
if (!p){
np->suf=root;
tot+=np->calc();
}
else{
Node *q=p->go[w];
if (p->val+1==q->val){
np->suf=q;
tot+=np->calc();
}
else{
Node *nq=newNode();
memcpy(nq->go,q->go,sizeof(q->go));
tot-=p->calc()+q->calc();
nq->val=p->val+1;
nq->suf=q->suf;
q->suf=nq;
np->suf=nq;
tot+=p->calc()+q->calc()+np->calc()+nq->calc();
while (p&&p->go[w]==q){
p->go[w]=nq;
p=p->suf;
}
}
}
last = np;
}
public:
void init(){
cur=nodePool;
root=newNode();
last=root;
}
VI getSubString(char s[]){
VI v;
tot=0;
int len=strlen(s);
for (int i=0;i<len;i++){
extend(s[i]-'a');
v.push_back(tot);
}
return v;
}
int getLCS(char A[],char B[]){
int res=0,step=0;
int lenA=strlen(A);
int lenB=strlen(B);
for (int i=0;i<lenA;i++) extend(A[i]-'a');
Node *p=root;
for (int i=0;i<lenB;i++){
int x=B[i]-'a';
if (p->go[x]){
step++;
p=p->go[x];
}
else{
while (p&&!p->go[x]) p=p->suf;
if (!p){
p=root;
step=0;
}
else{
step=p->val+1;
p=p->go[x];
}
}
res=max(res,step);
}
return res;
}
}atm;
char A[maxn],B[maxn];
int main()
{
while (~scanf("%s%s",A,B)){
atm.init();
printf("%d\n",atm.getLCS(A,B));
}
return 0;
}
-----------------
-----------------
-----------------