"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; }