2017 CCPC 哈尔滨 A (hdu 6230) Palindrome (Manacher + BIT)
2017-11-12 17:51
447 查看
解题思路:
题目中要求的回文串大致为 ______ i ____ j ______ 分别以 i j 为中心的两个回文串
我们可以使用Manacher算法先处理出以每个字符为中心的回文串的长度,注意这里求出来的回文串长度一定都是奇数
然后我们令 p[i] 为以第 i 个字符为中心的回文半径
然后一个字符串想要满足题意需要满足下面三个条件
j > i
j-i <= p[i]
j-i <= p[j]
我们可以把最后一个式子移项 得到 i >= j - p[j] ①
所以我们可以每次把 满足①条件的 j 放入树状数组中,然后每次求在 ( i , i+p[i] ] 范围内的j有多少
AC代码:
/*
* @Author: wchhlbt
* @Last Modified time: 2017-11-12
*/
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define pb push_back
#define AA first
#define BB second
#define ONES(x) __builtin_popcount(x)
#define _ << " " <<
using namespace std;
typedef pair<int, int> P;
typedef long long ll ;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
const double eps =1e-3;
const int mod = 1000000007;
const double PI = acos(-1.0);
inline int read(){ int num; scanf("%d",&num); return num;}
const int maxn = 500007;
char Ma[maxn*2];
int Mp[maxn*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;
}
char s[maxn];
int p[maxn];
vector<int> g[maxn];
//BIT 向下统计 向上修改
int bit[maxn];
int n;
int sum(int i)
{
int s = 0;
while(i>0){
s += bit[i];
i -= i & -i;
}
return s;
}
void add(int i, int x)//i 不能取 0
{
while(i<=n){
bit[i] += x;
i += i&-i;
}
}
int main()
{
int t = read();
while(t--){
//init
memset(bit,0,sizeof bit);
for(int i = 0; i<maxn; i++) g[i].clear();
scanf("%s",s);
int slen = strlen(s);
int len = Manacher(s,slen);
int k = 1;
for(int i = 2; i<len; i+=2){
p[k] = Mp[i]/2 -1;
//cout << k _ p[k] _ Mp[i] << endl;
g[k-p[k]].pb(k);
k++;
}
n = slen;
ll ans = 0;
for(int i = 1; i<=n; i++){
for(int j = 0; j<g[i].size(); j++)
add(g[i][j],1);
ans += sum(min(i+p[i],n)) - sum(i);
}
cout << ans << endl;
}
return 0;
}
题目中要求的回文串大致为 ______ i ____ j ______ 分别以 i j 为中心的两个回文串
我们可以使用Manacher算法先处理出以每个字符为中心的回文串的长度,注意这里求出来的回文串长度一定都是奇数
然后我们令 p[i] 为以第 i 个字符为中心的回文半径
然后一个字符串想要满足题意需要满足下面三个条件
j > i
j-i <= p[i]
j-i <= p[j]
我们可以把最后一个式子移项 得到 i >= j - p[j] ①
所以我们可以每次把 满足①条件的 j 放入树状数组中,然后每次求在 ( i , i+p[i] ] 范围内的j有多少
AC代码:
/*
* @Author: wchhlbt
* @Last Modified time: 2017-11-12
*/
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define pb push_back
#define AA first
#define BB second
#define ONES(x) __builtin_popcount(x)
#define _ << " " <<
using namespace std;
typedef pair<int, int> P;
typedef long long ll ;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
const double eps =1e-3;
const int mod = 1000000007;
const double PI = acos(-1.0);
inline int read(){ int num; scanf("%d",&num); return num;}
const int maxn = 500007;
char Ma[maxn*2];
int Mp[maxn*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;
}
char s[maxn];
int p[maxn];
vector<int> g[maxn];
//BIT 向下统计 向上修改
int bit[maxn];
int n;
int sum(int i)
{
int s = 0;
while(i>0){
s += bit[i];
i -= i & -i;
}
return s;
}
void add(int i, int x)//i 不能取 0
{
while(i<=n){
bit[i] += x;
i += i&-i;
}
}
int main()
{
int t = read();
while(t--){
//init
memset(bit,0,sizeof bit);
for(int i = 0; i<maxn; i++) g[i].clear();
scanf("%s",s);
int slen = strlen(s);
int len = Manacher(s,slen);
int k = 1;
for(int i = 2; i<len; i+=2){
p[k] = Mp[i]/2 -1;
//cout << k _ p[k] _ Mp[i] << endl;
g[k-p[k]].pb(k);
k++;
}
n = slen;
ll ans = 0;
for(int i = 1; i<=n; i++){
for(int j = 0; j<g[i].size(); j++)
add(g[i][j],1);
ans += sum(min(i+p[i],n)) - sum(i);
}
cout << ans << endl;
}
return 0;
}
相关文章推荐
- ccpc哈尔滨A [HDU-6230] Palindrome Manacher+树状数组
- 2017 ccpc哈尔滨 A题 Palindrome
- 2017 CCPC 哈尔滨 M ( hdu 6242) Geometry Problem (随机化 + 三角形外心)
- HDU 6242 Geometry Problem(2017 CCPC 哈理工)(随机化+计算几何)
- 简单规律 HDU - 6154 CaoHaha's staff[2017 CCPC网络选拔赛]
- 2017CCPC女生赛 hdu 6031 Innumerable Ancestors
- hdu 6152 : Friend-Graph (2017 CCPC网络赛 1003)
- HDU 6237 A Simple Stone Game(CCPC 2017 哈理工)(素数分解+贪心)(好题)
- CCPC 2017 哈尔滨 H题
- hdu6237-2017哈尔滨CCPC-质因子&贪心&暴力-A Simple Stone Game
- 2017CCPC女生赛 hdu 6030 Happy Necklace
- A Secret 2017 CCPC 网络选拔赛 hdu 6153
- [Manacher+bit]Palindrome
- 2017哈尔滨ccpc部分题解
- HDU 6230 Palindrome(主席树)
- ural1297 Palindrome,hdu 3068 最长回文,Manacher
- CCPC 2017 哈尔滨 F题
- HDU 6252 CCPC FINAL 2017
- CCPC 2017 哈尔滨赛区现场赛 比赛总结
- 【(好题)组合数+Lucas定理+公式递推(lowbit+滚动数组)+打表找规律】2017多校训练七 HDU 6129 Just do it