码迷,mamicode.com
首页 > 其他好文 > 详细

CodeChef 3-Palindromes(Manacher)

时间:2015-02-22 13:22:57      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:

3-Palindromes

 
Problem code: PALIN3
 

All submissions for this problem are available.

Read problems statements in Mandarin Chinese and Russian as well.

Mike likes strings. He is also interested in algorithms. A few days ago he discovered for himself a very nice problem:


You are given a digit string S. You need to count the number of substrings of S, which are palindromes.

Do you know how to solve it? Good. Mike will make the problem a little bit more difficult for you.


You are given a digit string S. You need to count the number of substrings of S, which are palindromes without leading zeros and can be divided by 3 without a remainder.

A string is a palindrome if it reads the same backward as forward. A string is a palindrome without leading zeros if it reads the same backward as forward and doesn‘t start with symbol ‘0‘. A string is a digit string, if it doesn‘t contain any symbols except ‘0‘, ‘1‘, ‘2‘, ..., ‘9‘.

Please, note that you should consider string "0" as a palindrome without leading zeros.

Input

The first line of the input contains a digit string S.

Output

Your output should contain the only integer, denoting the number of substrings of S, which are palindromes without leading zeros and can be divided by 3 without a remainder.

Constraints

1 ≤ |S| ≤ 1 000 000

Example

Input:
1045003

Output:
4

Explanation

In the example you should count S[2..2] = "0", S[5..5] = "0", S[6..6] = "0" and S[7..7] = "3".

 

给出一个数字串。

问有多少个子串既是回文串也能被3整除~

先用Manacher处理好串的回文串长度。

然后用一个数组 cnt[i][j] 表示sigma( 1 ~  i-1 到i 的数 ) %3 == j 串的个数。

 

技术分享
#include <bits/stdc++.h>

using namespace std;
typedef long long LL ;
typedef pair<LL,LL> pii;
#define X first
#define Y second
const int N = 2000010;
char Ma[N] , s[N];
int Mp[N] , len ;
void 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( Ma[i+Mp[i]] == Ma[i-Mp[i]] ) {
            Mp[i]++;
        }
        if( i + Mp[i] > mx ) {
             mx = i + Mp[i];
            id = i ;
        }
    }
}

bool is_dig( char op ) {
    if( op >= 0 && op <= 9 ) return true ;
    return false ;
}
LL cnt[N][3] , sum[N] ;

void Run() {
    int n = strlen(s) ;
    Manacher(s,n);
    len = 2 * n + 2 ;
    memset( sum , 0 , sizeof sum );
    memset( cnt , 0 , sizeof cnt );
    for( int i = 1 ; i < len ; ++i ){
           sum[i] = sum[i-1];
        if( is_dig(Ma[i]) ) sum[i] += ( Ma[i] - 0 );
    }
    for( int i = 2 ; i < len ; ++i ) {
        if( !is_dig(Ma[i]) || Ma[i] == 0 ) {
            for( int j = 0 ; j < 3 ; ++j )
                cnt[i][j] = cnt[i-1][j];
        }
        else {
            int x = Ma[i] - 0 ;
            for( int j = 0 ; j < 3 ; ++j ) {
                int _j = (j+x)%3;
                cnt[i][_j] += cnt[i-1][j] ;
            }
            cnt[i][x%3]++;
        }
    }
    LL ans = 0 ;
    for( int i = 2 ; i < len ; ++i ) {
        int x = 0 , tmp = sum[i-1] - sum[i-Mp[i]] ;
        if( is_dig(Ma[i]) ) {
            x = Ma[i] - 0 ;
            if( x % 3 == 0 ) ans++ ;
        }
        for( int j = 0 ; j < 3 ; ++j ) {
            if( ( 2*j + x )%3 == 0 ) {
                ans += cnt[i-1][j];
                for( int z = 0 ; z < 3 ; ++z ) if( (z+tmp)%3 == j ){
                    ans -= cnt[i-Mp[i]][z];
                }
            }
        }
    }
    printf("%lld\n",ans);
}

int main()
{
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
    int _ , cas = 1 ;
    while( scanf("%s",s) != EOF )Run();
}
View Code

 

CodeChef 3-Palindromes(Manacher)

标签:

原文地址:http://www.cnblogs.com/hlmark/p/4297425.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!