Cod sursa(job #1138380)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 9 martie 2014 22:23:49
Problema PScPld Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.86 kb
#include <iostream>
#include <fstream>
#include <cstring>

using namespace std;

const int NMax = 2000010;
char a[NMax * 2], v[NMax];
int n;
long long ans;
int dp[NMax];
/// dp[i] = jumatate din lungimea maxima a unui palindrom de lungime impara cu centrul in i

int main()
{
    ifstream f("pscpld.in");
    f>>(v+1);
    f.close();
    n = strlen(v+1);
    int sz = 0;
    for(int i = 1; i<=n; ++i)
        a[++sz] = '$', a[++sz] = v[i];
    a[sz + 1] = '$';
    ++sz;
    n = sz;
    //cout<<(a+1);
    int maxim = 1; /// valoarea cea mai mare pentru j + dp[j] adica cel mai din dreapta capat al unui palindrom centrat in j cu j < i
    int position = 1; /// position = acel j pentru care j + dp[j] e maxim
    dp[1] = 0;
    for (int i = 2; i <= n; ++i)
    {
        if (maxim < i)
        {
            int st, dr;
            for (st = dr = i; st - 1 >= 1 && dr + 1 <= n && a[st - 1] == a[dr + 1]; --st, ++dr);
            dp[i] = (dr - st) / 2;
            maxim = i + dp[i];
            position = i;
        }
        else
        {
            int iprim = position - (i - position); /// iprim = simetricul lui i fata de position
            if (dp[iprim] + i < maxim)
                dp[i] = dp[iprim];
            else
            {
                /// luam pana la maxim si apoi cautam brut restul palindromului (daca exista)
                /// si actualizam maximul.
                dp[i] = min(dp[iprim], maxim - i);
                int st, dr;
                for (dr = maxim, st = i - (maxim - i); st - 1 >= 1 && dr + 1 <= n && a[st - 1] == a[dr + 1]; --st, ++dr, ++dp[i]);
				if (i + dp[i] > maxim)
					maxim = i + dp[i], position = i;
            }
        }
    }
    for (int i = 1; i <= n; ++i)
        ans += 1LL * (dp[i] + 1) / 2;
    ofstream g("pscpld.out");
    g<<ans<<"\n";
    g.close();
    return 0;
}