[Learning] SAM

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值