【后缀自动机】[SPOJ LCS]Longest Common Substring

模板题目,感觉和用AC自动机差不多,就是一个一个字符在自动机里面匹配,找不到就沿着失配边往上走,然后如果当前节点变成了null那么就不能继续匹配,就把当前设置成root然后len变成0,否则就沿着边继续走,然后把len变成当前的节点的len+1因为是失配边,所以前边的都可以匹配,变成当前的len+1

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 200;
struct node{
    node *p[26], *pre;
    int len;
    node(){
        memset(p, 0, sizeof p);
        pre = NULL;
        len = 0;
    }
}Edges[MAXN*2+10], *ecnt=Edges+1,*root=Edges,*last=Edges;
void Insert(int w){
    node *np = ecnt++;
    node *p = last;
    while(p&&!p->p[w])
        p->p[w]=np, p=p->pre;
    if(!p){
        np->pre = root;
    }else{
        node *q = p->p[w];
        if(p->len+1 == q->len){
            np->pre = q;
        }else{
            node *nnd = ecnt++;
            memcpy(nnd->p, q->p, sizeof (nnd->p));
            nnd->len = p->len+1; nnd->pre = q->pre; q->pre = nnd; np->pre = nnd;
            while(p&&p->p[w]==q)
                p->p[w]=nnd, p=p->pre;
        }
    }
    last = np;
}
const int MAXT = 1000;
char s1[MAXT+10], s2[MAXT+10];
int main(){
    int ans = 0, len = 0;
    scanf("%s %s", s1, s2);
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    for(int i=0;i<len1;i++)
        Insert(s1[i]-'a');
    node *p = root;
    for(int j=0;j<len2;j++){
        int now = s2[j]-'a';
        if(p->p[now])
            p = p->p[now], len++;
        else{
            while(p&&!p->p[now])
                p = p->pre;
            if(!p)
                len=0, p = root;
            else
                len=p->len+1, p=p->p[now];
        }
        ans = max(len, ans);
    }
    printf("%d\n", ans);

    return 0;
}

posted on 2015-06-06 14:34  JeremyGuo  阅读(133)  评论(0编辑  收藏  举报

导航