Tony's Log

Algorithms, Distributed System, Machine Learning

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

"not more than 1000000 digits" means an efficient in-place solution is needed. My first solution was string<->int conversion based. It worked for small ints, but got TLE with large numbers.

Thanks to http://www.bytehood.com/spoj-the-next-palindrome/418/ that shed lights on me. The key idea is the same as my first idea: simply keep increasing digits near the center digit(s), and we only need figure out left half of the digits since it is mirrored palindrome. 

(I saw a lot of rejudge requests in SPOJ comments.. several erroneous results got returned from AC code. Mine's also rejected due to wrong answer - I think rejudge is needed)

Corner cases are important to this problem: single digits, all 9s, carry-over situation etc. Here is my code:

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;

int dCarry = 0;
int findLgRInx(char *str, int len, int i_l)
{
    int i_mis = -1;
    int i = i_l;
    while(i-- >= 0)
    {
        if(str[i] > str[len - 1 - i])
        {
            i_mis = i;
            break;
        }
    }
    return i_mis;
}

void incLHalf(char *str, int len, int i_l)
{
    int i = i_l;
    while(i >= 0)
    {
        int d = str[i] - '0';
        if(d < 9)
        {
            str[i] = (d + 1) + '0';
            return;
        }
        else
        {
            str[i] = '0';
            if(i > 0)
            {
                int nd = str[i-1]-'0';
                if(nd < 9)
                {
                    str[i-1] = (nd + 1) + '0';
                    return;
                }                
            }
            else
            {
                dCarry = 1;
                return;
            }
        }
        i--;
    }
}

void copyl2r(char *str, int len, int i_l)
{
    int i = i_l;
    while(i >= 0)    
    {
        str[len-i-1] = str[i];        
        i--;
    }
}

void calc_next_palin(char *str)
{
    unsigned len = strlen(str);
    if(len == 1)        
    {
        int i = atoi(str);
        cout << (i + 1) + i / 9 << endl;
        return;
    }
    
    int i_l = 0, i_r = 0;
    if(len % 2 == 0)
    {
        i_l = len / 2 - 1;
        i_r = len / 2;
        int i_mis = findLgRInx(str, len, i_l);
        if(i_mis != -1)
        {
            copyl2r(str, len, i_mis);
            cout << str << endl; 
            return;
        }
        else
        {
            incLHalf(str, len, i_l);
            copyl2r(str, len, i_l);
            if(dCarry == 0)
            {
                cout << str << endl;                
            }
            else
            {
                cout << "1" << str << "1" << endl;                
            }
            return;
        }
    }
    else    //odd
    {
        int i_c = len / 2;
        int i_mis = findLgRInx(str, len, i_c + 1);
        if(i_mis != -1)
        {
            copyl2r(str, len, i_mis);
            cout << str << endl;            
        }
        else
        {
            int dmid = str[i_c] - '0';
            if(dmid < 9)
            {
                str[i_c] = (dmid + 1) + '0';                
            }
            else
            {
                str[i_c] = '0';
                incLHalf(str, len, i_c - 1);
                copyl2r(str, len, i_c);
            }
            if(dCarry == 0)            
            {
                cout << str << endl;
            }
            else
            {
                cout << "1" << str << "1" << endl;
            }
        }        
        return;
    }
}

int main() 
{
    int cnt; cin >> cnt;    
    if(cnt == 0) return 0;
    
    //
    while(cnt --)
    {
        string str; cin >> str;            
        calc_next_palin((char*)str.c_str());        
    }
    return 0;
} 
View Code

 

posted on 2014-02-06 02:43  Tonix  阅读(224)  评论(0编辑  收藏  举报