#include<bits/stdc++.h>
using namespace std;
constexpr int MAXN = 1 << 20, LOGN = 21;
int table[LOGN][MAXN];
void build(int N, vector<int> &V) {
copy(V.begin(), V.begin()+N, table[0]);
for (int j = 1; j < LOGN; j++) {
for (int i = 0; i + (1 << j) <= N; i++) {
table[j][i]=min(table[j-1][i],
table[j-1][i+(1<<j)/2]);
}
}
}
int query(int l, int r) {
int k = 31 - __builtin_clz(r - l); // [l, r)
return min(table[k][l], table[k][r-(1 << k)]);
}
using ll = long long;
#define f first
#define s second
template<class T> using V = vector<T>;
using vi = V<int>;
using vpi = V<pair<int,int>>;
#define sz(x) int((x).size())
#define pb push_back
#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define each(a,x) for (auto& a: x)
#define all(x) begin(x), end(x)
template<class T> bool ckmin(T& a, const T& b) {
return b < a ? a = b, 1 : 0; } // set $a = \min(a,b)$
vi sa_is(const vi& s, int upper) { //Suffix array $\mathcal{O}(n)$
int n=sz(s);if(!n)return {}; vi sa(n);vector<bool> ls(n);
for(int i=n-1;i--;)ls[i]=s[i]==s[i+1]?ls[i+1]:s[i]<s[i+1];
vi sum_l(upper), sum_s(upper);
F0R(i,n) (ls[i] ? sum_l[s[i]+1] : sum_s[s[i]])++;
F0R(i,upper) {
if (i) sum_l[i] += sum_s[i-1];
sum_s[i] += sum_l[i];
}
auto induce = [&](const vi& lms) {
fill(all(sa),-1); vi buf = sum_s;
for (int d: lms) if (d != n) sa[buf[s[d]]++] = d;
buf = sum_l; sa[buf[s[n-1]]++] = n-1;
F0R(i,n){//do l-type in increasing order,suf[v]>suf[v+1]
int v = sa[i]-1;
if (v >= 0 && !ls[v]) sa[buf[s[v]]++] = v;
}
buf = sum_l;
for(int i=n-1; i>=0; --i){
int v=sa[i]-1;//s-type in decr. order,suf[v]<suf[v+1]
if (v >= 0 && ls[v]) sa[--buf[s[v]+1]] = v;
}
};
vi lms_map(n+1,-1), lms; int m = 0;
FOR(i,1,n)if(!ls[i-1] && ls[i])lms_map[i]=m++,lms.pb(i);
induce(lms);vi sorted_lms;// sorts LMS prefixes
each(v,sa)if(lms_map[v]!=-1)sorted_lms.pb(v);
vi rec_s(m); int rec_upper = 0; // smaller subproblem
FOR(i,1,m){ //compare two lms substrings in sorted order
int l=sorted_lms[i-1], r=sorted_lms[i]; bool same = 0;
int end_l = lms_map[l]+1 < m ? lms[lms_map[l]+1] : n;
int end_r = lms_map[r]+1 < m ? lms[lms_map[r]+1] : n;
if(end_l-l == end_r-r){
for (;l < end_l && s[l] == s[r]; ++l,++r);
if (l != n && s[l] == s[r]) same = 1;
}
rec_s[lms_map[sorted_lms[i]]] = (rec_upper += !same);
}
vi rec_sa = sa_is(rec_s,rec_upper+1);
F0R(i,m) sorted_lms[i] = lms[rec_sa[i]];
induce(sorted_lms); return sa;
}
struct SuffixArray { //tested with $n \leq 5\cdot 10^5$ (226 ms)
string S; int N; vi sa, isa, lcp; //N=sz(S)+1=n+1
void init(string _S) { //$\mathcal{O}(n\log n)$
N=sz(S=_S)+1;vi s(N);FOR(i,0,N-1)s[i]=S[i]-'a';
sa=sa_is(s,27);isa=vi(N);FOR(i,0,N)isa[sa[i]]=i;genLcp();}
void genSa() { // sa has size sz(S)+1, sa[0]=sz(S)
sa = isa = vi(N); sa[0] = N-1; iota(1+all(sa),0);
sort(1+all(sa),[&](int a,int b){return S[a]<S[b];});
FOR(i,1,N) { int a = sa[i-1], b = sa[i];
isa[b] = i > 1 && S[a] == S[b] ? isa[a] : i; }
for (int len = 1; len < N; len *= 2) { // currently
// sorted by first len chars
vi s(sa), is(isa), pos(N); iota(all(pos),0);
each(t,s){
int T=t-len;if(T>=0)sa[pos[isa[T]]++]=T;
}
FOR(i,1,N) {
int a = sa[i-1], b = sa[i];
// verify that nothing goes out of bounds
isa[b] = is[a]==is[b]&&
is[a+len]==is[b+len]?isa[a]:i;
}
}//sa[i]= indice (0-based) d'inizio i-esimo...
} //... prefisso più piccolo
// isa[i] = x t.c. sa[x]=i
//lcp[i]=lcp tra sa[i] e sa[i+1] ($0\leq i \leq n-1$)
void genLcp(){
lcp=vi(N-1); int h=0; //lcp[0]=lcp(sz(S),sa[1])=0
F0R(b,N-1) { int a = sa[isa[b]-1];
while (a+h < sz(S) && S[a+h] == S[b+h]) ++h;
lcp[isa[b]-1] = h; if (h) h--; }
build(N-1,lcp); // serve rmq (del booklet)
//ma va modificato con vector<int>& anzichè int*
//e V.begin() anzichè V
//if we cut off first chars of two strings with...
} //...lcp h then remaining portions still have lcp h-1
//lcp of suffixes starting at a,b
int getLCP(int a, int b){
if (a == b) return sz(S)-a; // a,b sono 0-based
int l = isa[a], r = isa[b]; if (l > r) swap(l,r);
return query(l,r); // serve rmq (del booklet)
}
};
void solve(){
string s;
int n;
cin>>s;
n=s.size();
SuffixArray tmp;
tmp.init(s);
assert(tmp.lcp[0]==0);
int last=0,ans=0;
for(int i=0;i<s.size()/2;i++){
if(s[last]==s[s.size()-1-i] && tmp.getLCP(last,s.size()-1-last-(i-last))>=(i-last+1)){
last=i+1;
ans+=2;
}
}
if(last!=s.size()/2 || s.size()%2==1)ans++;
cout<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)solve();
return 0;
}
Compilation message
palindromic.cpp: In function 'void solve()':
palindromic.cpp:132:16: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
132 | for(int i=0;i<s.size()/2;i++){
| ~^~~~~~~~~~~
palindromic.cpp:139:10: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
139 | if(last!=s.size()/2 || s.size()%2==1)ans++;
| ~~~~^~~~~~~~~~~~
palindromic.cpp:124:7: warning: variable 'n' set but not used [-Wunused-but-set-variable]
124 | int n;
| ^
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
0 ms |
340 KB |
Output is correct |
2 |
Correct |
0 ms |
340 KB |
Output is correct |
3 |
Correct |
0 ms |
340 KB |
Output is correct |
4 |
Correct |
0 ms |
340 KB |
Output is correct |
5 |
Correct |
0 ms |
340 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
0 ms |
340 KB |
Output is correct |
2 |
Correct |
0 ms |
340 KB |
Output is correct |
3 |
Correct |
0 ms |
340 KB |
Output is correct |
4 |
Correct |
0 ms |
340 KB |
Output is correct |
5 |
Correct |
0 ms |
340 KB |
Output is correct |
6 |
Correct |
1 ms |
340 KB |
Output is correct |
7 |
Correct |
0 ms |
340 KB |
Output is correct |
8 |
Correct |
1 ms |
340 KB |
Output is correct |
9 |
Correct |
0 ms |
340 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
0 ms |
340 KB |
Output is correct |
2 |
Correct |
0 ms |
340 KB |
Output is correct |
3 |
Correct |
0 ms |
340 KB |
Output is correct |
4 |
Correct |
0 ms |
340 KB |
Output is correct |
5 |
Correct |
0 ms |
340 KB |
Output is correct |
6 |
Correct |
1 ms |
340 KB |
Output is correct |
7 |
Correct |
0 ms |
340 KB |
Output is correct |
8 |
Correct |
1 ms |
340 KB |
Output is correct |
9 |
Correct |
0 ms |
340 KB |
Output is correct |
10 |
Correct |
5 ms |
1132 KB |
Output is correct |
11 |
Correct |
3 ms |
1108 KB |
Output is correct |
12 |
Correct |
4 ms |
1088 KB |
Output is correct |
13 |
Correct |
5 ms |
980 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
0 ms |
340 KB |
Output is correct |
2 |
Correct |
0 ms |
340 KB |
Output is correct |
3 |
Correct |
0 ms |
340 KB |
Output is correct |
4 |
Correct |
0 ms |
340 KB |
Output is correct |
5 |
Correct |
0 ms |
340 KB |
Output is correct |
6 |
Correct |
1 ms |
340 KB |
Output is correct |
7 |
Correct |
0 ms |
340 KB |
Output is correct |
8 |
Correct |
1 ms |
340 KB |
Output is correct |
9 |
Correct |
0 ms |
340 KB |
Output is correct |
10 |
Correct |
5 ms |
1132 KB |
Output is correct |
11 |
Correct |
3 ms |
1108 KB |
Output is correct |
12 |
Correct |
4 ms |
1088 KB |
Output is correct |
13 |
Correct |
5 ms |
980 KB |
Output is correct |
14 |
Correct |
596 ms |
101972 KB |
Output is correct |
15 |
Correct |
405 ms |
97520 KB |
Output is correct |
16 |
Correct |
504 ms |
94272 KB |
Output is correct |
17 |
Correct |
491 ms |
51092 KB |
Output is correct |