ACdream 1430 SETI 后缀自动机

来源:互联网 发布:淘宝账号注册首页登录 编辑:程序博客网 时间:2024/05/22 08:23

题目大意:

就是对于给定的串S, 长度不超过10000, 求出其有多少种子串T, 使得T在S中至少不重叠地出现了2次以上


大致思路:

很明显的后缀自动机吧, 建立S的后缀自动机, 记录每个节点对应的串出现的最左和最右位置, 以及出现次数, dfs遍历一遍后缀自动机上的点即可了

细节见代码吧


代码如下:

Result  :  Accepted     Memory  :  7076 KB     Time  :  8 ms

/* * Author: Gatevin * Created Time:  2015/5/20 20:29:44 * File Name: Rin_Tohsaka.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define foreach(e, x) for(__typeof(x.begin()) e = x.begin(); e != x.end(); ++e)#define SHOW_MEMORY(x) cout<<sizeof(x)/(1024*1024.)<<"MB"<<endl#define maxn 20010#define maxm 10010struct Suffix_Automation{    struct State    {        State *par;        State *go[26];        int right, val, leftmost, rightmost, mi;        bool vis;        void init(int _val = 0)        {            par = 0, leftmost = 1e9 + 7, rightmost = -1, val = _val, right = 0, mi = 0;            vis = 0;            memset(go, 0, sizeof(go));        }    };    State *root, *last, *cur;    State nodePool[maxn];    void init()    {        cur = nodePool;        root = newState();        last = root;    }    State* newState(int val = 0)    {        cur->init(val);        return cur++;    }    void extend(int w, int pos)    {        State *p = last;        State *np = newState(p->val + 1);        np->right = 1;        np->leftmost = pos, np->rightmost = pos;        while(p && p->go[w] == 0)        {            p->go[w] = np;            p = p->par;        }        if(p == 0)        {            np->par = root;        }        else        {            State *q = p->go[w];            if(p->val + 1 == q->val)            {                np->par = q;            }            else            {                State *nq = newState(p->val + 1);                memcpy(nq->go, q->go, sizeof(q->go));                nq->par = q->par;                q->par = nq;                np->par = nq;                while(p && p->go[w] == q)                {                    p->go[w] = nq;                    p = p->par;                }            }        }        last = np;    }    State* b[maxn];    int d[maxm];    void topo()    {        int cnt = cur - nodePool;        int maxVal = 0;        memset(d, 0, sizeof(d));        for(int i = 1; i < cnt; i++)            maxVal = max(maxVal, nodePool[i].val), d[nodePool[i].val]++;        for(int i = 1; i <= maxVal; i++) d[i] += d[i - 1];        for(int i = 1; i < cnt; i++) b[d[nodePool[i].val]--] = &nodePool[i];        b[0] = root;    }    void info()    {        int cnt = cur - nodePool;        State *p;        for(int i = cnt - 1; i > 0; i--)        {            p = b[i];            p->par->right += p->right;            p->mi = p->par->val + 1;            p->par->leftmost = min(p->par->leftmost, p->leftmost);            p->par->rightmost = max(p->par->rightmost, p->rightmost);        }    }    int ans;    void dfs(State *now)    {        now->vis = 1;        if(now->right >= 2 && now != root)        {            int len2 = now->rightmost - now->leftmost;            if(now->val <= len2) ans += now->val - now->mi + 1;            else if(now->mi <= len2) ans += len2 - now->mi + 1;        }        for(int i = 0; i < 26; i++)            if(now->go[i] && !now->go[i]->vis)                dfs(now->go[i]);        return;     }    void solve()    {        ans = 0;        dfs(root);        printf("%d\n", ans);    }};Suffix_Automation sam;char in[10010];int main(){    while(scanf("%s", in) != EOF)    {        int len = strlen(in);        sam.init();        for(int i = 0; i < len; i++)            sam.extend(in[i] - 'a', i);        sam.topo();        sam.info();        sam.solve();    }    return 0;}


0 0