Palindrome
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1267 Accepted Submission(s): 469
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$.
在做这道题时,刚刚复习了Manachar,好久没有写Manachar,所以有很多Bug。
题意中定义一个字符串,S[i]=S[2n−i]=S[2n+i−2](1≤i≤n) ,根据观察可以知道题目中要求的回文串大致为
______ i ____ j ______ 分别以 i j 为中心的两个回文串。所以首先用Manachar预处理字符串,获得以每个字符为中心的回文串长度,即p[i] 为以i为中心的回文串的半径长度。
题意中定义的字符串有三个要求:
i < j
p[i] + i >= j
j <= i + p[j]
将 第三个式子变形为 j - p[j] <= i ,
所以我们可以每次把 满足条件j - p[j] <= i的 j 放入树状数组中,然后每次求在 ( i , i+p[i] ] 范围内的j有多少
/*************************************************************************
> File Name: hdu6230.cpp
> Author: ccdxc
> Created Time: 2019年04月17日 星期三 13时43分07秒
************************************************************************/
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int INF = 0x3f3f3f3f;
const int Maxn = 5e5 + 10;
string str;
int T ,bit[Maxn] ,len , n;
int lowbit(int x){
return x & -x;
}
void add(int i , int x){
while(i <= n){
bit[i] += x;
i += lowbit(i);
}
}
int sum(int i){
int ans = 0;
while(i > 0){
ans += bit[i];
i -= lowbit(i);
}
return ans;
}
vector<int>mp[Maxn];
int main(){
cin >> T;
while(T--){
for(int i = 0;i <= n ;i++) mp[i].clear() , bit[i] = 0;
cin >> str;
//Manachar预处理字符串
string s = "$#";
n = str.length();
for(int i = 0;i < n;i++) s += str[i] , s += "#";
len = s.length();
vector<int>p(len , 0);
int mx = 0 , id = 0;
for(int i = 1;i < len ;i++){
p[i] = mx > i? min(mx - i , p[id * 2 - i]):1;
while(s[i + p[i]] == s[i -p[i]]) p[i]++;
if(p[i] + i > mx){
mx = p[i] + i;
id= i;
}
}
for(int i = 2;i < len;i += 2){
//cout <<p[i] <<" ";
p[i / 2] = p[i] / 2 - 1;
mp[(i/2) - p[i / 2]].pb(i / 2);
}
//cout << endl;
ll ans = 0;
for(int i = 1;i <= n ; i++){
for(int j = 0;j < mp[i].size();j++){
add(mp[i][j] ,1);
}
ans += (ll)sum(min(n , i + p[i])) - (ll)sum(i);
}
cout << ans <<endl;
}
}