zoukankan      html  css  js  c++  java
  • codeforces 432D Prefixes and Suffixes

    由于包含了前缀与后缀,很容易想到用KMP去算前缀与后缀的公共缀。另外要计算某个后缀在整个串中出现的次数,由于后缀自动机是比较容易求的,然后就直接上后缀自动机了。先分别用KMP算法与后缀自动机跑一遍,然后对后缀自动机做一个拓扑排序,根据拓扑结构更新一遍每个串出现的次数就可以了。然后直接沿着KMP的next数组以及后缀自动机节点的父亲边走就可以了。

    代码如下:

    #include <stdio.h>
    #include <string.h>
    const int maxn = 100100;
    
    struct sanode{
        sanode *f, *ch[26];
        int l, m;
        sanode(){
            f = 0;
            memset(ch, 0, sizeof(ch));
            l = 0, m = 1;
        }
        void init(){
            f = 0;
            memset(ch, 0, sizeof(ch));
            l = 0, m = 1;
        }    
    }sam[maxn*2], *b[maxn*2];
    int cnt[maxn], tot;
    sanode *tail, *s;
    char str[maxn];
    int f[maxn]; //KMP
    struct resultSet{
        int l, m;
    }res[maxn];
    
    void addSuffix(int c, int len){
        sanode *p = tail, *np = &sam[++tot];
        np->init();
        tail = np;
        np->l = len;
    
        for(;p&&!p->ch[c];p=p->f) p->ch[c] = np;
        if(!p) np->f = s;
        else{
            if(p->ch[c]->l == p->l + 1) np->f = p->ch[c];
            else{
                sanode * q = p->ch[c], *r = &sam[++tot];
                *r = *q;
                r->l = p->l + 1;
                r->m = 0;
                q->f = np->f = r;
                for(;p && p->ch[c]==q; p=p->f) p->ch[c] = r;
            }
        }
    }
    
    void topSortSuffix(int len){
        for(int i = 0; i <= tot; i ++) cnt[sam[i].l] ++;
        for(int i = 1; i <= len; i ++) cnt[i] += cnt[i-1];
        for(int i = 0; i <= tot; i ++) b[--cnt[sam[i].l]] = &sam[i];
    
        for(int i = tot; i > 0; i --){
            b[i]->f->m += b[i]->m;
        }
    }
    void KMP(){
        int c = 0;
        for(int i = 2; str[i]; i ++){
            while(c && str[c+1] != str[i])
                c = f[c];
            if(str[c+1] == str[i])
                f[i] = ++c;
        }
    }
    
    int main(){
        int len = 0;
        s = tail = &sam[tot = 0];
        s->init();
        scanf("%s", str+1);
        for(len = 1; str[len]; len ++){
            addSuffix(str[len] - 'A', len);
        }
        len --;
        topSortSuffix(len);
        KMP();
        sanode *p = tail;
        int number = 0;
        for(; len; len = f[len]){
            while(p && p->l > len)
                p = p->f;
            if(!p) break;
            if(p->l == len){
                res[number].l = len;
                res[number].m = p->m;
                number ++;
            }
        }
        printf("%d
    ", number);
        for(int i = number - 1; i >= 0; i --)
            printf("%d %d
    ", res[i].l , res[i].m);
        
        return 0;
    }
  • 相关阅读:
    μTorrent for Windows
    坚决抵制Rarbg的恶意修改版
    Check YouTube Video Restrictions Online
    Questions about "Computer Systems: A Programmer's Perspective"
    los diccionarios que te acercan al mundo
    sqlserver 备份数据库 按时间命名备份文件
    Linux中的硬链接和软链接的概念、区别及用法
    高恪固件端口映射怎么配置
    C++中的DLL,Delphi调用需要注意之一
    Delphi中主线程与子线程调用同一方法同步问题
  • 原文地址:https://www.cnblogs.com/bootstar/p/3885616.html
Copyright © 2011-2022 走看看