[Learning] SAM

来源:互联网 发布:薛定谔的猫 知乎 编辑:程序博客网 时间:2024/06/04 17:47

From cxlove

资料

http://fanhq666.blog.163.com/blog/static/8194342620123352232937/

题目

http://www.spoj.pl/problems/NSUBSTR/ 

这题基本上就是套个木板T_T 。 借鉴的cxlove 和 UESTC 神奇的 后缀三兄弟 Orz 

cxlove mua ~

const int N = 250009;namespace SAM{const int CHAR = 26;const int LEN = N << 1;struct SAM_Node{    SAM_Node *fa , *son[CHAR];    int len , id , pos , g;    SAM_Node(){}    SAM_Node(int _len){        g = 0;        fa = 0;        len = _len;        RST(son);    }};SAM_Node node[LEN << 1] , *root , *last;int SAM_size;SAM_Node * newNode(int len){    node[SAM_size] = SAM_Node(len);    node[SAM_size].id = SAM_size;    return &node[SAM_size++];}SAM_Node *newNode(SAM_Node * p){    node[SAM_size] = *p;    node[SAM_size].id = SAM_size;    return &node[SAM_size++];}void init(){    SAM_size = 0;    root = last = newNode(0);    node[0].pos = 0;}void add(int x , int len){    SAM_Node *p = last , *np = newNode(p -> len + 1);    np -> pos = len;    last = np;    for( ; p && !p -> son[x] ; p = p -> fa)        p -> son[x] = np;    if (!p){        np -> fa = root;        return;    }    SAM_Node *q = p -> son[x];    if (q -> len == p -> len + 1){        np -> fa = q;        return;    }    SAM_Node * nq = newNode(q);    nq -> len = p -> len + 1;    q -> fa = nq;    np -> fa = nq;    for ( ; p && p -> son[x] == q ; p = p -> fa)        p -> son[x] = nq;}void build(char * s){    init();    int len = strlen(s);    REP(i , len)        add(s[i] - 'a' , i + 1);}}using namespace SAM;char str[N];int dp[N] , n , topocnt[N];SAM_Node *topsam[LEN];void solve(){    n = strlen(str);    build(str);    RST(topocnt);    REP(i , SAM_size)        topocnt[node[i].len] ++;    REP_1(i , n) topocnt[i] += topocnt[i - 1];    REP(i , SAM_size) topsam[ -- topocnt[node[i].len] ] = &node[i];    REP(i , n) (root = root -> son[str[i] - 'a']) -> g++;    RST(dp);    for (int i = SAM_size - 1 ; i > 0 ; i--){        checkMax(dp[ topsam[i] -> len ] , topsam[i] -> g);        if (topsam[i] -> fa) topsam[i] -> fa -> g += topsam[i] -> g;    }    for (int i = n - 1 ; i > 0 ; i--) checkMax(dp[i] , dp[i + 1]);    REP_1(i , n) printf("%d\n" , dp[i]);}int main(){    while(~scanf("%s" , str)) solve();}


http://www.spoj.pl/problems/LCS/

const int N = 250009;const int CHAR = 26;namespace SAM{    struct Node{        Node * fa , *next[CHAR];        int len , id , pos;        Node(){}        Node(int _len){            fa = 0;            len = _len;            RST(next);        }    };    Node node[N << 1] , *root , *last;    int size;    Node * newnode(int len){        node[size] = Node(len);        node[size].id = size;        return &node[size++];    }    Node * newnode(Node * p){        node[size] = *p;        node[size].id = size;        return &node[size++];    }    void init(){        size = 0;        root = last = newnode(0);        node[0].pos = 0;    }    void add(int x , int len){        Node *p = last , *np = newnode(p -> len + 1);        np -> pos = len;        last = np;        for( ; p && !p -> next[x] ; p = p -> fa)            p -> next[x] = np;        if (!p){            np -> fa = root;            return;        }        Node *q = p -> next[x];        if (q -> len == p -> len + 1){            np -> fa = q;            return;        }        Node * nq = newnode(q);        nq -> len = p -> len + 1;        q -> fa = nq;        np -> fa = nq;        for( ; p && p -> next[x] == q ; p = p -> fa)            p -> next[x] = nq;    }    void build(char * s){        init();        int l = strlen(s);        REP(i , l)            add(s[i] - 'a' , i + 1);    }}using namespace SAM;char str[N] , s[N];int ans , l , n , topcnt[N];Node* topo[N << 1] , *now;void solve(){    n = strlen(str);    build(str);    RST(topcnt);    REP(i , size)        topcnt[node[i].len]++;    REP_1(i , n) topcnt[i] += topcnt[i - 1];    REP(i , size) topo[ -- topcnt[node[i].len] ]  = &node[i];    n = strlen(s);    ans = 0 , l = 0;    now = root;    REP(i , n){        int x = s[i] - 'a';        if(now -> next[x]){            l++;            now = now -> next[x];        }        else{            while(now && now -> next[x] == NULL)                now = now -> fa;            if (!now){                l = 0;                now = root;            }            else{                l = now -> len + 1;                now = now -> next[x];            }        }        checkMax(ans , l);    }    OT(ans);}int main(){    while(~scanf("%s%s" , str , s)) solve();}


http://www.spoj.pl/problems/LCS2/ 

const int N = 100009;const int CHAR = 26;namespace SAM{    struct Node{        Node * fa , *next[CHAR];        int len , id , pos;        int curlen , minlen;        Node(){}        Node(int _len){            fa = 0;            len = _len;            RST(next);        }    };    Node node[N << 1] , *root , *last;    int size;    Node * newnode(int len){        node[size] = Node(len);        node[size].id = size;        return &node[size++];    }    Node * newnode(Node * p){        node[size] = *p;        node[size].id = size;        return &node[size++];    }    void init(){        size = 0;        root = last = newnode(0);        node[0].pos = 0;    }    void add(int x , int len){        Node *p = last , *np = newnode(p -> len + 1);        np -> pos = len;        last = np;        for( ; p && !p -> next[x] ; p = p -> fa)            p -> next[x] = np;        if (!p){            np -> fa = root;            return;        }        Node *q = p -> next[x];        if (q -> len == p -> len + 1){            np -> fa = q;            return;        }        Node * nq = newnode(q);        nq -> len = p -> len + 1;        q -> fa = nq;        np -> fa = nq;        for( ; p && p -> next[x] == q ; p = p -> fa)            p -> next[x] = nq;    }    void build(char * s){        init();        int l = strlen(s);        REP(i , l)            add(s[i] - 'a' , i + 1);    }}using namespace SAM;char str[N];int ans , l , n , topcnt[N];Node* topo[N << 1] , *now;void solve(){    n = strlen(str);    build(str);    RST(topcnt);    REP(i , size)        topcnt[node[i].len]++;    REP_1(i , n) topcnt[i] += topcnt[i - 1];    for (int i = size - 1 ; i >= 0 ; --i) topo[ -- topcnt[node[i].len] ]  = &node[i];    REP(i , size){        topo[i] -> minlen = topo[i] -> len;    }    while(~scanf("%s" , str)){        REP(i , size) topo[i] -> curlen = 0;            int len = 0; now = root;        REP_C(i , strlen(str)){//                OT(str[i]);            int x = str[i] - 'a';            while(now -> fa && now -> next[x] == NULL) now = now -> fa , len = now -> len;            if(now -> next[x]){                len++;                now = now -> next[x];                checkMax(now -> curlen , len);            }            else{                len = 0;                now = root;            }        }        for (int i = size - 1 ; i >= 0 ; --i){            now = topo[i];            checkMin(now -> minlen , now -> curlen);            if (now -> fa) checkMax(now -> fa -> curlen , now -> curlen);        }    }    ans = 0;    for (int i = 0 ; i < size ; ++i)        checkMax(ans , node[i].minlen);    OT(ans);}int main(){    scanf("%s" , str); solve();}


http://www.spoj.pl/problems/SUBLEX/ 
http://acm.hdu.edu.cn/showproblem.php?pid=4436 
http://acm.hdu.edu.cn/showproblem.php?pid=4416 
http://acm.hdu.edu.cn/showproblem.php?pid=4270 
http://codeforces.com/contest/235/problem/C