HDU 6230 Palindrome Manacher+树状数组

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)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)S[i]=S[2n−i]=S[2n+i−2](1≤i≤n).For example, abcbabcabcbabc is one-and-half palindromic string, and abccbaabcabccbaabc 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 500000500000), 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$.

题意:给你t个字符串,定义1.5倍回文串为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

和j都都为回文串的中点其中每个串的长度为(j-i)*2,比如abab,abcbabc,问你这个5e5的串里面有多少个这样的回文串。

思路:这什么1.5倍回文串,暴力想都别想,但是我们可以用Manacher算法预处理一下,把每个字符组成回文串想两边可以延伸的长度len[]处理出来,这样直接找一对i,j使i+len[i]>=j&&j-len[i]<=i,这样是就是一个1.5倍回文串了,但是如果暴力枚举一个i的len的话那么复杂度又被拉回到了n*n了,一定不能过,开始的时候除了怎么找一个i符合要求的j其他的思路都想到了,还是自己太菜了,线段树,优先队列,贪心,都想过,实在想不出来了,最后去看了下题解,居然是树状数组,知道要用树状数组后自己也想了好长一段时间,就是想不到,怎么去解决这个问题,最后没办法了,仔细的看看别人的代码,才明白了树状数组是怎么处理的。先枚举记录一个字符可以延伸到前面的那个地方cnt-maxr,在记录那个点时谁能及的,然后记录开始遍历每一个字符,把所有到该点的点都加入到树状数组,然后计算sum(i+maxr)-sum(i),这样就保证了i+len[i]>=j&&j-len[i]<=i十分的巧妙,想了好久的确没想到。

代码:

#include<stdio.h>
#include<string.h>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
const ll linf=8e18+9e17;
const int mod=1e9+7;
const double e=exp(1.0);
const double pi=acos(-1);
const double eps=1e-6;
char s[maxn],ss[maxn];
int len[maxn],sum[maxn],maxs[maxn];
vector<int>v[maxn];
int lowbit(int x)
{
	return x & - x;
}
void updata(int x,int data)
{
	while(x<maxn)
	{
		sum[x]+=data;
		x+=lowbit(x);
	}	
}
int getsum(int x)
{
	int ans=0;
	while(x>0)
	{
		ans+=sum[x];
		x-=lowbit(x);
	}
	return ans;
}
int Manacher()
{
	int ls=strlen(s),lss=1;
	ss[0]='!';
	for(int i=0;i<ls;i++)
	{
		ss[lss++]='#';
		ss[lss++]=s[i];
	}
	ss[lss++]='#';
	ss[lss++]='@';
	int maxr=-1,j=-1,mid;
	for(int i=1;i<lss;i++)
	{
		if(maxr>i)len[i]=min(len[mid*2-i],maxr-i);
		else len[i]=1;

		while(ss[i-len[i]]==ss[i+len[i]])len[i]++;
		
		if(len[i]+i>maxr)maxr=len[i]+i,mid=i;
	}
	return lss;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s",s);
		memset(sum,0,sizeof sum);
		int l=Manacher(),cnt=1;
		ll ans=0;
		for(int i=2;i<l;i+=2,cnt++)
		{
			maxs[cnt]=len[i]/2-1;
			v[cnt-maxs[cnt]].push_back(cnt);
		}
		for(int i=1;i<=cnt;i++)
		{
			for(int j=0;j<v[i].size();j++)
			updata(v[i][j],1);
			ans+=(ll)(getsum(i+maxs[i])-getsum(i));
			v[i].clear();
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/swust5120166213/article/details/82988488
今日推荐