您的位置:首页 > 其它

Codeforces Beta Round #7 D. Palindrome Degree manacher算法+dp

2016-09-06 01:28 302 查看

题目链接:

http://codeforces.com/problemset/problem/7/D

D. Palindrome Degree

time limit per test1 secondmemory limit per test256 megabytes

问题描述


String s of length n is called k-palindrome, if it is a palindrome itself, and its prefix and suffix of length are (k - 1)-palindromes. By definition, any string (even empty) is 0-palindrome.

Let's call the palindrome degree of string s such a maximum number k, for which s is k-palindrome. For example, "abaaba" has degree equals to 3.

You are given a string. Your task is to find the sum of the palindrome degrees of all its prefixes.


输入


The first line of the input data contains a non-empty string, consisting of Latin letters and digits. The length of the string does not exceed 5·106. The string is case-sensitive.


输出


Output the only number — the sum of the polindrome degrees of all the string's prefixes.


样例输入


a2A


样例输出


1


样例输入


abacaba


样例输出


6


题意


假设前缀prei是k-回文串(k=a[i])。则求ans=sigma(a[i])。


题解


用manacher算法处理出最左端为第一个字母的所有回文串,然后dp一下。

dp[i]表示长度为i的前缀是k-回文串(k=dp[i])。 则dp[i]=dp[i/2]+1;

ans=sigma(dp[i]);


代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long  LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=1e7+10;

char s[maxn];
//P[i]表示把回文串折叠起来的长度
//mx表示当前计算出来的回文串往右延伸的最远端
//d表示贡献出mx的串的回文中心
int P[maxn],mx,id,n;
LL dp[maxn];

LL solve(){
LL ret=0;
int len=strlen(s+1);
n=len*2+1;
s[0]='$',s
='#',s[n+1]='\0';
for(int i=len*2;i>=1;i--){
if(i&1) s[i]='#';
else s[i]=s[i/2];
}
//    puts(s);
clr(dp,0);
mx=1,id=0;
for(int i=1;i<=n;i++){
//优化的核心,画画图比较好理解,j=2*id-i表示i关于id对称的点
P[i]=mx>i?min(mx-i,P[2*id-i]):1;
int k=i+P[i];
while(s[k]==s[2*i-k]) k++,P[i]++;
if(2*i-k==0&&i>1){
//            bug(i);
int l=P[i]-1;
dp[l]=dp[l/2]+1;
ret+=dp[l];
}
if(k>mx){
mx=k;
id=i;
}
}
return ret;
}

int main() {
scf("%s",s+1);
LL ans=solve();
prf("%I64d\n",ans);
return 0;
}

//end-----------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: