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;
}

-----------------

-----------------

-----------------

你可能感兴趣的:(SPOJ 1811 Longest Common Substring SAM)