POJ 1509 Glass Beads(SAM 求最小表示法)

来源:互联网 发布:金山毒霸网络卸载密码 编辑:程序博客网 时间:2024/05/29 05:55

题目链接:http://poj.org/problem?id=1509

最小表示法有另外的方法,这里给的是用后缀自动机的求法

把原串自身组合一下,然后建立这个组合串的后缀自动机,从根开始每次沿着最小的边

走原串长度就可以了!

  最后结果为什么会是这个printf("%d\n",p->val-len+1);?

因为最终走到的位置是最小串的结尾,那么结果就显然了!

PS:nq 写成 np debug好久!

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>using namespace std;#define maxn 12000struct point{    point *next[26],*father;    int val;    int init(){        memset(next,0,sizeof(next));        father=NULL;        val=0;        return 0;    }}po[maxn*5],*tail;int pos;char str[maxn];int len;int add(int l){    point *np=&po[pos++],*p=tail;    np->init();    np->val=tail->val+1;    while(p && p->next[l]==NULL) p->next[l]=np,p=p->father;    if(p==NULL) np->father=&po[0];    else{        point *q=p->next[l];        if(p->val+1==q->val) np->father=q;        else{            point *nq=&po[pos++];nq->init();            *nq=*q;            nq->val=p->val+1;            q->father=np->father=nq;            while(p && p->next[l]==q) p->next[l]=nq,p=p->father;        }    }    tail=np;    return 0;}int solve(int len){    point *p=&po[0];    for(int i=0;i<len;i++)    for(int j=0;j<26;j++)    if(p->next[j]){        p=p->next[j];        break;    }    printf("%d\n",p->val-len+1);    return 0;}int main(){    int i,j,k,t;    scanf("%d",&t);    while(t--){        pos=1;tail=&po[0];po[0].init();        scanf("%s",str);        len=strlen(str);        for(i=0;i<len;i++)        add(str[i]-'a');        for(i=0;i<len;i++)        add(str[i]-'a');        solve(len);    }    return 0;}


原创粉丝点击