Pagini recente » Cod sursa (job #31685) | Cod sursa (job #1288061) | Cod sursa (job #113739) | Cod sursa (job #948626) | Cod sursa (job #908638)
Cod sursa(job #908638)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>
using namespace std;
ifstream f("pscpld.in");
ofstream g("pscpld.out");
#define nmax 1000004
#define ll long long
string A, S;
int lung[nmax*2];
void citeste(){
getline(f, A);
}
int extinde(int st, int dr){
int cnt = 0;
for(int i=st, j=dr; i>=0&&j<S.size(); i--, ++j){
if (S[i] != S[j]) return cnt;
++cnt;
}
return cnt;
}
void bagaManacher(){
//lung[i] = cat de mult ma pot extinde in dreapta(evident si la stanga); e mai ok asa
lung[0] = 0;
int dr = -1; int centru = -1;
for(int i=1; i<S.size(); ++i){
if (dr < i){
lung[i] = extinde(i-1, i+1);
dr = i + lung[i]; centru = i;
continue;
}
// acum dr >= i(i intra in zBox)
int i2 = centru - (i-centru);// simetricul lui i fata de centru
int lungBeta = dr - i;// secventa i+1..dr; fac abstractie de caracterul i;
if (lung[i2] < lungBeta) lung[i] = lung[i2];// clar
else {
lung[i] = lungBeta + extinde(i-lungBeta-1, i+lungBeta+1);
}
if (dr < i + lung[i]){
dr = i + lung[i]; centru = i;
}
}
}
void rezolva(){
//algoritmul lui manacher
int ceva = A.size()-1;
for(int i=0; i<ceva; ++i){
S += A[i]; S+='#';
}
S += A[ A.size()-1 ];
bagaManacher();
// acum numar secventele palindroame
ll Rez = 0;
for(int i=0; i<S.size(); ++i){
if (S[i] == '#'){// acum e palindrom de genul i, i+1 in vechiul string
int cnt = lung[i]/2 + (lung[i]%2); // lungimea palindromului va fi 2 * cnt; dar in total sunt doar cnt palindroame cu centrul in i,i+1
Rez += (ll)cnt;
}else {// e simplu de centru i
int cnt = lung[i]/2 + 1;
Rez += (ll)cnt;
}
}
g << Rez << "\n";
}
int main(){
citeste();
rezolva();
f.close();
g.close();
return 0;
}