1. 程式人生 > >HDU 6230 Palindrome Manacher+樹狀陣列

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;
}