SPOJ 1811 Longest Common Substring SAM
-----------------
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; }
-----------------
-----------------
-----------------