Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
Problem Description
Alice like strings, especially long strings. For each string, she has a special evaluation system to judge how elegant the string is. She defines that a string
S
[
1..3
n
−
2
]
(
n
≥
2
)
S[1..3n−2](n≥2)
S[1..3n−2](n≥2) is one-and-half palindromic if and only if it satisfies
S
[
i
]
=
S
[
2
n
−
i
]
=
S
[
2
n
+
i
−
2
]
(
1
≤
i
≤
n
)
S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)
S[i]=S[2n−i]=S[2n+i−2](1≤i≤n).For example,
a
b
c
b
a
b
c
abcbabc
abcbabc is one-and-half palindromic string, and
a
b
c
c
b
a
a
b
c
abccbaabc
abccbaabc is not. Now, Alice has generated some long strings. She ask for your help to find how many substrings which is one-and-half palindromic.
Input
The first line is the number of test cases. For each test case, there is only one line containing a string(the length of strings is less than or equal to
500000
500000
500000), this string only consists of lowercase letters.
Output
For each test case, output a integer donating the number of one-and-half palindromic substrings.
Sample Input
1
ababcbabccbaabc
Sample Output
2
Hint
In the example input, there are two substrings which are one-and-half palindromic strings, a b a b abab abab and a b c b a b c abcbabc abcbabc.
题意:
输出字符串s中,"一又一半字符串"的数量
“一又一半字符串” : 字符串
S
[
1..3
n
−
2
]
(
n
≥
2
)
S[1..3n−2](n≥2)
S[1..3n−2](n≥2),满足了
S
[
i
]
=
S
[
2
n
−
i
]
=
S
[
2
n
+
i
−
2
]
(
1
≤
i
≤
n
)
S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)
S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)
题解:
很显然这个字符串是一个奇数长度的字符串。
我们先用马拉车做出对于每个中点
i
i
i的最长回文串长度的半径
r
[
i
]
r[i]
r[i]。
然后很显然,我们考虑两个拼在一起的回文串的中点
i
,
j
(
i
>
j
)
i,j(i>j)
i,j(i>j)
只需要满足
j
+
r
[
j
]
−
1
<
=
i
j+r[j]-1<=i
j+r[j]−1<=i且
i
−
r
[
i
]
+
1
>
=
j
i-r[i]+1>=j
i−r[i]+1>=j
那么我们把所有
i
−
r
[
i
]
+
1
i-r[i]+1
i−r[i]+1相同的
i
i
i存在一起
然后枚举
j
=
i
−
r
[
i
]
+
1
j=i-r[i]+1
j=i−r[i]+1,把所有的这些
i
i
i的树状数组位置都+1
然后查询区间
[
j
,
j
+
r
[
j
]
−
1
]
[j,j+r[j]-1]
[j,j+r[j]−1]区间的元素之和。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int lowbit(int x){return x&(-x);}
char s[500004];
int n,r[500004];
int tr[500004];
vector<int>vec[500004];
ll ans;
void add(int x){
for(int i=x;i<=n;i+=lowbit(i))tr[i]++;
}
int ask(int x){
int ret=0;
for(int i=x;i>0;i-=lowbit(i))ret+=tr[i];
return ret;
}
int w33ha(){
ans=0;
scanf("%s",s);
n=strlen(s);
for(int i=0;i<=n;i++)tr[i]=0;
for(int i=0;i<=n;i++)vec[i].clear();
for(int i=0;i<n;i++)r[i]=0;
int mx=0,id=0;
for(int i=0;i<n;i++){
r[i]=(mx>i)?min(r[id*2-i],mx-i):1;
while(i-r[i]>=0&&i+r[i]<n&&s[i-r[i]]==s[i+r[i]])r[i]++;
if(i+r[i]>mx){
mx=i+r[i];
id=i;
}
}
for(int i=n;i>=1;i--)r[i]=r[i-1];
for(int i=1;i<=n;i++){
vec[i-r[i]+1].push_back(i);
}
for(int i=1;i<=n;i++){
for(int j=0;j<vec[i].size();j++){
add(vec[i][j]);
}
ans+=ask(i+r[i]-1)-ask(i);
}
printf("%lld\n",ans);
return 0;
}
int main(){
int T;scanf("%d",&T);
while(T--)w33ha();
return 0;
}