zoukankan      html  css  js  c++  java
  • CodeChef 3-Palindromes(Manacher+dp)

    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
    ",ans);
    }
    
    int main()
    {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        int _ , cas = 1 ;
        while( scanf("%s",s) != EOF )Run();
    }
    View Code
  • 相关阅读:
    搭建Android开发环境(linux x86_64)
    prisoner of love
    今天火箭和太阳打架了?
    归途,奋斗的起点
    年轻的希望
    老师:节日快乐!
    今天是我的生日吗?
    我亲爱的弟弟
    我的08,期盼09
    只是向往
  • 原文地址:https://www.cnblogs.com/hlmark/p/4297425.html
Copyright © 2011-2022 走看看