Cod sursa(job #1517379)

Utilizator fluture.godlikeGafton Mihnea Alexandru fluture.godlike Data 4 noiembrie 2015 10:19:54
Problema Substr Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 kb
#include <cstdio>
#include <cstring>
#include <algorithm>

#define DIM 2000007
#define log2 24

using namespace std;
char s[DIM];
int n, sum, edge, suffix[log2][DIM];
struct dinamica
{
    int st;
    int dr;
    int pos;
} v[DIM];

bool cmp(const dinamica &a, const dinamica &b)
{
    if(a.st != b.st) return (a.st < b.st);
    return (a.dr < b.dr);
}
inline void add_revert()
{
    edge = n;
    for(int i = n; i; --i) s[++edge] = s[i];
}
inline void convert_string()
{
    for(int i = 1; i<= edge; ++i)
    {
        s[i] -= 'a'- 1;
    }
}
inline void construct_suffix_array()
{
    for(int i = 1; i<= edge; ++i) suffix[0][i] = s[i];
    for(int pas = 1; (1<<(pas-1)) < n; ++pas)
    {
        for(int i = 1; i<= edge; ++i)
        {
            v[i].st = suffix[pas-1][i];
            v[i].dr = suffix[pas-1][i + (1<<(pas-1))];
            v[i].pos = i;
        }
        sort(v+1, v+n+1, cmp);
        suffix[pas][v[1].pos] = 1;
        for(int i =2; i<= edge; ++i)
        {
            if(v[i].st == v[i-1].st && v[i].dr == v[i-1].dr) suffix[pas][v[i].pos] = suffix[pas][v[i-1].pos];
            else suffix[pas][v[i].pos] = i;
        }
    }
}
bool verificare(const int &p1, const int &p2, int p3, int p4)
{
    p3 = edge - p3 + 1;
    p4 = edge - p4 + 1;
    int lg = 0;
    for(; (1<<lg) < p4 - p3 + 1; lg++);
    --lg;
    if(suffix[lg][p1] == suffix[lg][p3] && suffix[lg][p2 - (1<<lg)+ 1] == suffix[lg][p4 - (1<<lg) + 1]) return 1;
    return 0;
}
int check_middle(const int &key)
{
    int start = 0, fin = min(key - 1, n-key), step = 1;
    for(; step <= fin; step <<= 1);
    step >>= 1;
    for( ; step; step>>=1)
    {
        int index = start + step;
        if(index > fin) continue;
        if(verificare(key, key + index, key, key - index)) start = index;
    }
    return start + 1;
}
int check_left(const int &key)
{
    int start = 0, fin = min(key-1, n-key-1), step = 1;
    for(; step <= fin; step <<= 1);
    step >>= 1;
    for( ; step; step>>=1)
    {
        int index = start + step;
        if(index > fin) continue;
        if(verificare(key+1, key + index+1, key, key - index)) start = index;
    }
    return start + 1;
}


int main()
{
    freopen("pscpld.in", "r", stdin);
    freopen("pscpld.out", "w", stdout);
    scanf("%s", s+1);
    n = strlen(s+1);
    add_revert();
    convert_string();
    construct_suffix_array();
    for(int i = 1; i<= n; ++i)
    {
        sum += check_middle(i);
        if(i == n) continue;
        if(s[i] == s[i+1]) sum += check_left(i);
    }
    printf("%d\n", sum);
    return 0;
}