codeforces 432D Prefixes and Suffixes
2014-08-01 18:17 bootstar 阅读(444) 评论(0) 编辑 收藏 举报由于包含了前缀与后缀,很容易想到用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\n", number); for(int i = number - 1; i >= 0; i --) printf("%d %d\n", res[i].l , res[i].m); return 0; }