CF 123D

http://codeforces.com/problemset/problem/123/D

sam应用


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>
#include <bitset>
//#pragma comment(linker, "/STACK:102400000,102400000")

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::stringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
using std::unique;
using std::lower_bound;
using std::random_shuffle;
using std::bitset;
using std::upper_bound;
using std::multiset;

typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UN;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
typedef LL TY;
typedef long double LF;

const int MAXN(100010);
const int MAXM(5010);
const int MAXE(505010);
const int MAXK(6);
const int HSIZE(1313);
const int SIGMA_SIZE(26);
const int MAXH(16);
const int INFI((INT_MAX-1) >> 1);
const ULL BASE(31);
const LL LIM(1e13);
const int INV(-10000);
const int MOD(31313);
const double EPS(1e-7);
const LF PI(acos(-1.0));

template<typename T> inline void checkmax(T &a, T b){if(b > a) a = b;}
template<typename T> inline void checkmin(T &a, T b){if(b < a) a = b;}
template<typename T> inline T ABS(const T &a){return a < 0? -a: a;}

struct NODE
{
    int mx, ri;
    NODE *f, *ch[SIGMA_SIZE];
};

int buc[MAXN];
NODE *rec[MAXN << 1];

struct SAM
{
    NODE pool[MAXN << 1], *rear;
    NODE *root, *last;
    void init()
    {
        last = root = pool;
        root->mx = root->ri = 0;
        root->f = 0;
        memset(root->ch, 0, sizeof(root->ch));
        rear = pool+1;
    }
    void extend(int id)
    {
        NODE *p = last, *np = rear++;
        last = np;
        np->ri = 1;
        np->mx = p->mx+1;
        memset(np->ch, 0, sizeof(np->ch));
        while(p && p->ch[id] == 0)
        {
            p->ch[id] = np;
            p = p->f;
        }
        if(p == 0) np->f = root;
        else
        {
            NODE *q = p->ch[id];
            if(q->mx == p->mx+1) np->f = q;
            else
            {
                NODE *nq = rear++;
                *nq = *q;
                nq->ri = 0;
                nq->mx = p->mx+1;
                np->f = q->f = nq;
                while(p && p->ch[id] == q)
                {
                    p->ch[id] = nq;
                    p = p->f;
                }
            }
        }
    }
    void topo()
    {
        int len = last->mx;
        memset(buc, 0, sizeof(buc[0])*(len+1));
        for(NODE *p = pool; p < rear; ++p) ++buc[p->mx];
        for(int i = 1; i <= len; ++i) buc[i] += buc[i-1];
        for(NODE *p = rear-1; p >= pool; --p) rec[--buc[p->mx]] = p;
    }
    LL solve()
    {
        LL ret = 0;
        for(int i = rear-pool-1; i > 0; --i) rec[i]->f->ri += rec[i]->ri;
        for(NODE *p = root+1; p < rear; ++p)
            ret += (LL)p->ri*(p->ri+1)/2*(p->mx-p->f->mx);
        return ret;
    }
} sam;

char str[MAXN];

int main()
{
    while(~scanf("%s", str))
    {   
        sam.init();
        for(char *sp = str; *sp; ++sp) sam.extend(*sp-'a');
        sam.topo();
        printf("%I64d\n", sam.solve());
    }
    return 0;
}




你可能感兴趣的:(CF 123D)