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

题目链接:

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

D. Palindrome Degree

time limit per test1 second
memory 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

include

include

include

include

include

include

include

include

include

include

include

include

include

include

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 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=len2+1;
s[0]='$',s[n]='#',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=2id-i表示i关于id对称的点
P[i]=mx>i?min(mx-i,P[2
id-i]):1;
int k=i+P[i];
while(s[k]s[2i-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-----------------------------------------------------------------------

posted @ 2016-09-06 01:28  fenicnn  阅读(339)  评论(0)    收藏  举报