poj1509 Glass Beads SAM

    最近打算把SAM撿回來,找個水題先練練手...這題是給一個字符串,首尾相連成環,求一個位置,使得從這個位置開始走一圈得到的串字典序最小。方法很多,後綴自動機也能做,把原串複製兩邊,一次插入到自動機中,然後從根節點開始,從小打到走len步,當前的位置就是最小字典序的串的位置了..

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <queue>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=20100;
const int S=26;
int tot,len;
int n,m;
int wtop[maxn<<1];
int c[maxn<<1];
int k,ans;

struct node
{
    node *pre,*go[S];
    int val,id;
}*tail,*root,que[maxn<<1],top[maxn<<1];
char str[maxn],s[maxn],ss[maxn];
inline int idx(char c)
{
    return c-'a';
}
struct SAM
{
    void init()
    {
        memset(que,0,sizeof que);
        tot=0;
        len=1;
        root=tail=&que[tot++];
        root->id=0;
        root->val=0;
    }
    void add(int c,int l)
    {
        node* p=tail;
        node* np=&que[tot++];
        np->val=l;
        np->id=tot-1;
        while(p && p->go[c]==NULL) p->go[c]=np,p=p->pre;
        if (p==NULL) np->pre=root;
        else
        {
            node* q=p->go[c];
            if (p->val+1==q->val) np->pre=q;
            else
            {
                node *nq=&que[tot++];
                *nq=*q;
                nq->id=tot-1;
                nq->val=p->val+1;
                np->pre=q->pre=nq;
                while(p && p->go[c]==q) p->go[c]=nq,p=p->pre;
            }
        }
        tail=np;
    }
    void debug_suff()
    {
        for (int i=0; i<tot; i++)
        {
            for (int c=0; c<S; c++)
            if (que[i].go[c])
            {
                cout<<que[i].id<<" "<<que[i].go[c]->id<<endl;
            }
        }
    }
    void debug_pre()
    {
        for (int i=1; i<tot; i++)
        cout<<que[i].id<<" "<<que[i].pre->id<<endl;
    }

}sam;
int main()
{
//    freopen("in.txt","r",stdin);
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%s",s);
        sam.init();
        int l=strlen(s);
        for (int i=0; i<l; i++)
        sam.add(idx(s[i]),len++);
        for (int i=0; i<l; i++)
        sam.add(idx(s[i]),len++);

//        sam.debug_suff();
//        puts("-----------------------------");
//        sam.debug_pre();
        node* rt=root;
        for (int i=0; i<l; i++)
            for (int c=0; c<S; c++)
            {
                if (rt->go[c])
                {
                    rt=rt->go[c];
                    break;
                }
            }
        printf("%d\n",rt->val-l+1);


    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章