Palindrome
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 426 Accepted Submission(s): 163
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
/************************************************************************* > File Name: A.cpp > Author: LyuCheng > Created Time: 2017-12-01 21:54 > Description: 题意:给你一个字符串问你有多少个子串满足s[i]=s[2*n-i]=s[2*n+i-2] 思路:满足条件的子串实际上是关于两点回文的一个子串,并且这个回文串 一定是奇数回文,用马拉车算法求出以每个点的回文半径,如果满足题 目的条件,设i<=pos[i]&&i-j<=pos[j] 用树状数组记录一下,然后统计 ************************************************************************/#include #define MAXN 567890#define lowbit(x) x&(-x)#define LL long longusing namespace std;int t;int n;char str[MAXN<<1];char tmp[MAXN<<1];int Len[MAXN<<1];int pos[MAXN<<1];int c[MAXN<<1];LL res;vector v[MAXN<<1];inline void update(int x){ while(x 0){ s+=c[x]; x-=lowbit(x); } return s;}int cal(char *st){ int i,len=strlen(st); tmp[0]='@';//字符串开头增加一个特殊字符,防止越界 for(i=1;i<=2*len;i+=2){ tmp[i]='#'; tmp[i+1]=st[i/2]; } tmp[2*len+1]='#'; tmp[2*len+2]='$';//字符串结尾加一个字符,防止越界 tmp[2*len+3]=0; return 2*len+1;//返回转换字符串的长度}//Manacher算法计算过程int manacher(char *st,int len){ int mx=0,ans=0,po=0;//mx即为当前计算回文串最右边字符的最大值 for(int i=1;i<=len;i++){ if(mx>i) Len[i]=min(mx-i,Len[2*po-i]);//在Len[j]和mx-i中取个小 else Len[i]=1;//如果i>=mx,要从头开始匹配 while(st[i-Len[i]]==st[i+Len[i]]) Len[i]++; if(Len[i]+i>mx){ //若新计算的回文串右端点位置大于mx,要更新po和mx的值 mx=Len[i]+i; po=i; } ans=max(ans,Len[i]); } return ans-1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度}inline void init(){ memset(str,'\0',sizeof str); memset(tmp,'\0',sizeof tmp); memset(c,0,sizeof c); memset(pos,0,sizeof pos); for(int i=0;i