【题目链接】
【思路要点】
- 补档博客,无题解。
【代码】
//PalindromicTree #include<bits/stdc++.h> using namespace std; #define MAXN 500005 int n; char s[MAXN]; struct Palindromic_Tree { int child[MAXN][26], ans; int father[MAXN], depth[MAXN]; int last, size; vector <int> a[MAXN]; bool mark[MAXN]; int new_node(int length) { memset(child[size], 0, sizeof(child[size])); father[size] = 0; depth[size] = length; return size++; } void Extend(int ch, int pos) { int p = last; while (s[pos - depth[p] - 1] != s[pos]) p = father[p]; if (!child[p][ch]) { int now = new_node(depth[p] + 2), q = father[p]; child[p][ch] = now; while (s[pos - depth[q] - 1] != s[pos]) q = father[q]; if (p == 0 || child[q][ch] == 0) father[now] = 1; else father[now] = child[q][ch]; } last = child[p][ch]; } void init() { size = 0; new_node(-1); new_node(0); father[1] = 0; last = 0; for (int i = 1; i <= n; i++) Extend(s[i] - 'a', i); } void work(int pos) { mark[depth[pos]] = true; if (depth[pos] % 4 == 0 && mark[depth[pos] / 2]) ans = max(ans, depth[pos]); for (unsigned i = 0; i < a[pos].size(); i++) work(a[pos][i]); mark[depth[pos]] = false; } int getans() { ans = 0; for (int i = 2; i < size; i++) a[father[i]].push_back(i); memset(mark, false, sizeof(mark)); work(1); return ans; } } PT; int main() { scanf("%d\n%s", &n, s + 1); PT.init(); printf("%d\n", PT.getans()); return 0; } //Manacher + SegmentTree #include<bits/stdc++.h> using namespace std; #define MAXN 1000005 struct SegMentTree { struct Node { int lc,rc; int maxnum; }; Node a[MAXN*2]; int size,n; private: void build(int now,int l,int r) { a[now].maxnum=0; if (l==r) return; int mid=(l+r)/2; a[now].lc=++size; build(size,l,mid); a[now].rc=++size; build(size,mid+1,r); } void update(int now) { if (a[now].lc==0) return; a[now].maxnum=max(a[a[now].lc].maxnum,a[a[now].rc].maxnum); } void maintain(int now,int l,int r,int x,int value) { if (l==r) { a[now].maxnum=value; return; } int mid=(l+r)/2; if (mid>=x) maintain(a[now].lc,l,mid,x,value); else maintain(a[now].rc,mid+1,r,x,value); update(now); } int query(int now,int l,int r,int ql,int qr) { if (l==ql && r==qr) return a[now].maxnum; int ans=0,mid=(l+r)/2; if (mid>=ql) ans=max(ans,query(a[now].lc,l,mid,ql,min(mid,qr))); if (mid+1<=qr) ans=max(ans,query(a[now].rc,mid+1,r,max(mid+1,ql),qr)); return ans; } public: void init(int x) { n=x;size=0; build(size,0,n); } void modify(int pos,int value) { maintain(0,0,n,pos/2,value); } int ask(int l,int r) { return query(0,0,n,l/2,r/2); } }; struct info {bool type;int value;}; char s[MAXN],x[MAXN]; int len[MAXN]; vector <info> operation[MAXN]; SegMentTree T; int main() { int n; scanf("%d",&n); scanf("\n%s",s+1); x[0]='$';x[1]='#';x[2*n+2]='%'; for (int i=1;i<=n;i++) {x[i*2]=s[i];x[i*2+1]='#';} int pos=0,r=0; for (int i=1;i<=2*n+1;i++) { if (i<=r) { int j=pos*2-i; if (len[j]<r-i+1) len[i]=len[j]; else { len[i]=r-i+1; while (x[i+len[i]]==x[i-len[i]]) len[i]++; pos=i;r=i+len[i]-1; } } else { len[i]=1; while (x[i+len[i]]==x[i-len[i]]) len[i]++; pos=i;r=i+len[i]-1; } } for (int i=0;i<=n;i++) { operation[2*i+1-len[2*i+1]+1].push_back((info){true,2*i+1}); operation[2*i+1].push_back((info){false,2*i+1}); } int ans=0; T.init(n); for (int i=0;i<=n;i++) { for (int j=0;j<operation[i*2+1].size();j++) if (operation[i*2+1][j].type) T.modify(operation[i*2+1][j].value,operation[i*2+1][j].value); else T.modify(operation[i*2+1][j].value,0); int tmp=T.ask(i*2+1,i*2+len[i*2+1]/2); ans=max(ans,(tmp-(i*2+1))/2); } printf("%d\n",ans*4); return 0; }