Palindrome
題面: 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…3n−2 ] (n≥2) is one-and-half palindromic if and only if it satisfies S[i]=S[ 2n−i ]=S [ 2n+i−2 ] (1≤i≤n).For example, abcbabc is one-and-half palindromic string, and 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.
題意: 給你一個字符串問你符合題目要求的子串有多少個
思路: 首先我們可以用馬拉車求出以每個位置爲中心的迴文串長度的一半,要符合要求需要兩個迴文串中心位置,所以我們可以用樹狀數組進行維護,求出總和
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
char s[N],Ma[N*2];
int mp[N*2],tree[N];
int p[N];
vector<int>t[N];
int len,l;
void add(int x,int v)
{
while(x<=len)
{
tree[x]+=v;
x+=(x & -x);
}
}
int sum(int x)
{
int res=0;
while(x>0)
{
res+=tree[x];
x-=(x & -x);
}
return res;
}
void Mana()
{
l=0;
Ma[l++]='$';
Ma[l++]='#';
for(int i=0;i<len;i++)
{
Ma[l++]=s[i];
Ma[l++]='#';
}
Ma[l++]='\0';
int mx=0,id=0;
for(int i=0;i<l;i++)
{
mp[i]=mx>i?min(mp[2*id-i],mx-i):1;
while(Ma[i+mp[i]]==Ma[i-mp[i]])mp[i]++;
if(i+mp[i]>mx)
{
mx=i+mp[i];
id=i;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
len=strlen(s);
memset(tree,0,sizeof tree);
for(int i=0;i<=len;i++)
t[i].clear();
Mana();
int cnt=1;
for(int i=2;i<l;i+=2)
{
p[cnt]=mp[i]/2-1;
t[cnt-p[cnt]].push_back(cnt);
cnt++;
}
ll ans=0;
for(int i=1;i<=len;i++)
{
for(int j=0;j<t[i].size();j++)
{
add(t[i][j],1);
}
ans+=sum(min(i+p[i],len))-sum(i);
}
printf("%lld\n",ans);
}
return 0;
}