CF17E Palisection

题意:给定一个长度为n的小写字母串。问你有多少对相交的回文子 串(包含也算相交) 。

题目传送门

日常敲模板2333

首先,相交的很不好找。

考虑等价问题,有多少对不相交的。用总数减去即可。

对于一个点i,从i-hw[i]到i,所有点都可以作为以i为中点的回文串的起点,统计终点同理。于是,就可以差分了,最后O(n)扫一遍统计即可。

代码简单。但这并不妨碍我写的丑。

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define ll long long
#define re register
#define inf 0x3f3f3f3f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug ");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
const ll mod=51123987;
const ll MAXN=2e6+10;
inl ll read() {
re ll x = 0; re int f = 1;
char ch = getchar();
while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x * f;
}
inl char readc() {
char ch=getchar();
while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
return ch;
}
inl void write(re ll x){
if(x>=10)write(x/10);
putchar(x%10+'0');
}
inl void writeln(re ll x){
if(x<0) {x=-x;putchar('-');}
write(x); puts("");
}
inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
inl ll Lcm(re ll a,re ll b) {return a/gcd(a,b)*b;}
inl void FR() {
freopen(".in","r",stdin);
freopen(".out","w",stdout);
}
inl void FC() {
fclose(stdin);
fclose(stdout);
}
ll n,nn,hw[MAXN<<1];
char s[MAXN],ss[MAXN<<1];
void manacher() {
ll mr=0,mid=0;
for(re ll i=1;i<=nn;i++) {
if(i<mr) hw[i]=min(hw[(mid<<1)-i],mid+hw[mid]-i);
else hw[i]=1;
while(ss[i-hw[i]]==ss[i+hw[i]]) hw[i]++;
if(i+hw[i]>mr) {mr=i+hw[i]-1;mid=i;}
}
}
ll f[MAXN<<1],g[MAXN<<1];
int main() {
// FR();
n=read();scanf("%s",s+1);
ss[0]=ss[1]='#';nn=n<<1|1;ll sum=0;
for(re ll i=1;i<=n;i++) {ss[i<<1]=s[i];ss[i<<1|1]='#';}
manacher();re ll tot=0;
for(re ll i=1;i<=nn;i++) {
tot=(tot+(hw[i]-1)/2)%mod;
if(!(i%2)) tot=(tot+1)%mod;
}
if(tot%2) {sum=((tot-1)/2*tot)%mod;}
else {sum=(tot/2*(tot-1))%mod;}
for(re ll i=1;i<=nn;i++) {
if(i%2) {
f[i-hw[i]+2]++;f[i+1]--;
g[i+hw[i]]--;g[i+1]++;
}
else {
f[i-hw[i]+2]++;f[i+2]--;
g[i+hw[i]]--;g[i]++;
}
}
for(re ll i=2;i<=nn;i+=2) {
f[i]=(f[i]+f[i-2])%mod;
g[i]=(g[i]+g[i-2])%mod;
}
f[nn+1]=0;
for(re ll i=nn-1;i>=2;i-=2) {f[i]=(f[i]+f[i+2])%mod;}
for(re ll i=2;i<=nn;i+=2) {sum=(sum-(g[i]*f[i+2])%mod+mod)%mod;}
writeln((sum+mod)%mod);
// FC();
return 0;
}

原文地址:https://www.cnblogs.com/20020723YJX/p/9387656.html