题目连接:HDU6230
Palindrome
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 567 Accepted Submission(s): 216
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..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.
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), 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, $abab$ and $abcbabc$.
题意:定义一个半回文串,问一个长串里有多少一个半回文串。
题目分析:首先用manacher处理字符串,获得每个字母为中心的回文串半径。
之后判断一个子串是否是一个半回文串:
_______i______j______若是一个半回文串的话需要满足以下3个条件:
i<j
j-i<=p[i]
j-i<=p[j]
对不等式进行移项,获得以下2个不等式:
i<j<=i+p[i]
i>=j-p[j]
问题转化为:对每个i,求在i到i+p[i]范围内有多少个j满足i>=j-p[j]。
预处理j-p[j],存在vector v[i]中,v[i]数组存的是满足j-p[j]==i的j的位置。
这样从前到后扫一遍i,每次使用树状数组update v[I]中的位置,然后求和统计sum(i+p[i])-sum(i)即可。
注意答案会比较大,需要用long long来存。
代码:
//
// main.cpp
// HDU 6230 Palindrome
//
// Created by teddywang on 2017/12/12.
// Copyright © 2017年 teddywang. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int T;
char s[1011111];
int p[1011111];
int c[511111];
vector<int> v[511111];
char Ma[511111*2];
int Mp[511111*2];
int Manacher(char s[],int len)
{
int 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(i-Mp[i]>=0 && Ma[i+Mp[i]]==Ma[i-Mp[i]]) Mp[i]++;
if(i+Mp[i]>mx)
{
mx=i+Mp[i];
id=i;
}
}
return l;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int num,int n)
{
while(x<=n)
{
c[x]+=num;
x+=lowbit(x);
}
}
int getsum(int x)
{
int s=0;
while(x>0)
{
s+=c[x];
x-=lowbit(x);
}
return s;
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(c,0,sizeof(c));
scanf("%s",s);
int slen = strlen(s);
for(int i = 0; i<=slen; i++) v[i].clear();
int len = Manacher(s,slen);
int k=1;
for(int i=2;i<len;i+=2)
{
p[k]=Mp[i]/2-1;
v[k-p[k]].push_back(k);
k++;
}
len=strlen(s);
long long ans=0;
for(int i=1;i<=len;i++)
{
int l=v[i].size();
for(int j=0;j<l;j++)
{
update(v[i][j],1,len);
}
ans+=getsum(min(i+p[i],len))-getsum(i);
}
printf("%lld\n",ans);
}
}