題目鏈結
題意:給你乙個只含a和b的字串,求不連續的回文子串行的個數。
題解:在每兩個字元之間補上乙個特殊字元。我們讓f[i]表示i左右兩邊(包括i)對稱(位置及字元相同)的字元的對數,則顯然2f
[i]' role="presentation" style="position: relative">2f[
i]2f
[i]為回文子串行的個數。但是題目要求的是不連續的,所以最後還要進行一次manacher,減掉連續的個數。
如何求f[i]?顯然f
[i]=
σ(j=
0..j−1
)s[i
−j]==
s[i+
j]' role="presentation" style="position: relative">f[i
]=σ(
j=0..j−1
)s[i
−j]==
s[i+
j]f[
i]=σ
(j=0..j−
1)s[
i−j]
==s[i
+j]
這是乙個卷積的形式。
我們弄兩個多項式,第乙個多項式a所有a的位置都是1,第二個多項式b左右b的位置都是1。我們用fft把a和b都平方一下,則顯然f[
i]=(
a[i∗
2]+b
[i∗2
]+1)
/2' role="presentation" style="position: relative">f[i
]=(a
[i∗2
]+b[
i∗2]
+1)/
2f[i
]=(a
[i∗2
]+b[
i∗2]
+1)/
2。最後的加一除以二是因為多項式平方的時候同乙個係數的結果被算了兩次,要去掉。
最後統計即可。
**:
#include
#include
#include
#include
using
namespace
std;
const
int n=530005,mod=1000000007;
const
double pi=3.141592653589793;
int len,n,m,rev[n],f[n],bin[n],p[n];
long
long ans;
char str[n],s[n];
struct
complex
complex(double x,double y):x(x),y(y){}
friend
complex
operator + (const
complex &a,const
complex &b)
friend
complex
operator - (const
complex &a,const
complex &b)
friend
complex
operator * (const
complex &a,const
complex &b)
}a[n],b[n];
void fft(complex *a,int dft)}}
if(dft==-1)
}}void manacher()
if(i+p[i]>maxr)
}}int main()
scanf("%s",str+1);
len=n=strlen(str+1);
s[0]='#';
for(int i=1;i<=n;i++)
for(int i=0;i<=m;i++)else
if(s[i]=='b')
}m*=2;
for(n=1;n<=m;n<<=1);
for(int i=0;i<=n;i++)
fft(a,1);
for(int i=0;i<=n;i++)
fft(a,-1);
fft(b,1);
for(int i=0;i<=n;i++)
fft(b,-1);
m/=2;
manacher();
for(int i=1;i<=m;i++)
printf("%lld\n",ans);
return
0;}
BZOJ3160 萬徑人蹤滅
對於每個可以作為對稱軸的位置,我們算出以其為對稱軸有多少對位置和字元是對稱的,設為t i 若不考慮不能連續,則我們可以從這t i 對里任選出來任意對,都是可行的答案,且不重不漏,所以不考慮不能連續的情況的答案為sigma 2 t i 1,考慮不能是連續子串,再減去回文子串的數量即可 回文子串數量ma...
BZOJ 3160 萬徑人蹤滅
給定乙個由 a 和 b 構成的字串,求不連續回文子串行的個數。正難則反我們考慮容斥。對於連續的回文字串顯然是一次馬拉車就可以很好的求出來的,那我們設f i 表示以i為中心的對稱字元對數量,顯然答案就是 2 n 1 12f i 1 那麼我們的問題就轉變成了怎麼求出f i 我們考慮當這個字元為a的時候做...
bzoj3160 萬徑人蹤滅
題目在上方鏈結 description input output sample input sample output hint source 2013湖北互測week1 首先將字串中間插入 把他們分隔開 題目要求求不連續的回文串的個數 那麼就用總數減去連續的即可 考慮連續的部分 直接用manach...