#include <iostream>
using namespace std;
char a[90]; //the initial number string
//对于 12,34 b[3] = 2 index_last = 1 b[1] = 0
int index_last; //求得的最后数字的大小,和分割点标记 index_last = b[strlen(a) - 1] - 1,最后一个数字a[index_last + 1:len_a - 1]
int path_now[90];
int path_best[90];
int cur = 1;
int cur_best = 1;
int b[90]; //b[i]存放到i位置为止的序列,按照题目要求最后一个数字的最小值(存前一坐标如2则值为a[2:i])
int len_a; //length of char array a
//return true only when a[s1,e1] < a[s2,e2]
bool IsLess(int s1, int e1, int s2, int e2)
{
if (s1 < 0)
return true;
while(s1 < e1 && a[s1] == '0') //delete the beginning 0
s1++;
while(s2 < e2 && a[s2] == '0')
s2++;
int len1 = e1 - s1 + 1;
int len2 = e2 - s2 + 1;
if (len1 < len2)
return true; //a[s1,e1] < a[s2,e2]
if (len1 > len2)
return false; //a[s1,e1] > a[s2,e2]
// len1 == len2
for (int i = 0; i < len1; i++) {
if (a[s1 + i] < a[s2 + i]) //a[s1,e1] < a[s2,e2]
return true;
if (a[s1 + i] > a[s2 + i]) //a[s1,e1] > a[s2,e2]
return false;
}
return false; //a[s1,e1] == a[s2,e2]
}
//return 1 a[s1,e1] < a[s2,e2]
//return 0 a[s1,e1] > a[s2,e2]
//return -1 a[s1,e1] == a[s2,e2]
int cmp(int s1, int e1, int s2, int e2)
{
if (s1 == s2 && e1 == e2)
return -1;
while(s1 < e1 && a[s1] == '0') //delete the beginning 0
s1++;
while(s2 < e2 && a[s2] == '0')
s2++;
int len1 = e1 - s1 + 1;
int len2 = e2 - s2 + 1;
if (len1 < len2)
return 1; //a[s1,e1] < a[s2,e2]
if (len1 > len2)
return 0; //a[s1,e1] > a[s2,e2]
for (int i = 0; i < len1; i++) {
if (a[s1 + i] < a[s2 + i]) //a[s1,e1] < a[s2,e2]
return 1;
if (a[s1 + i] > a[s2 + i]) //a[s1,e1] > a[s2,e2]
return 0;
}
return -1; //a[s1,e1] == a[s2,e2]
}
//找到最后一个数字,其数字大小存储在b[strlen(a) - 1]中
//what we store is b[] and index_last
void FindLast()
{
int start = 0;
while (a[start] == '0') //处理起始数字开头为0的情况,deal with 00001 treat as 1 ignore the starting 0
start++;
for (int i = start; i < len_a; i++) {
int j;
for (j = i; j > start; j--) { //对于每个位置i,求它的可能的最小的最后数字
if (IsLess(b[j - 1], j - 1, j, i)) { // if a[ b[j - 1] : j - 1] < a[j: i]
b[i] = j;
break;
}
}
if (j == start) {
b[i] = start;
}
if (i == (len_a - 1)) {
if (start != 0 && j == start) //00001
index_last = -1;
else
index_last = j - 1;
return;
}
}
index_last = -1; //like 0000 do not go into for loop
}
void PrintData(int start, int end);
//执行后将会得到前面的分割点坐标,并且cur指向下一个分割位置
//在已知最后最小尾数的情况下,递归搜索解法求解前面的分割,结合剪枝
bool FindSequence(int start, int end, int lstart, int lend, int path[])
{
while (start < end && a[start] == '0') //这个很重要不能少,有了这个预处理则长度大的就大,否则如0003与4影响判断
start++;
if (IsLess(start, end, index_last + 1, len_a - 1) &&
IsLess(lstart, lend, start, end)) {
return true;
}
for (int j = (start + (end + 1)) / 2; j > start; j--) {
//for (int j = end; j > start; j--) {
if (!IsLess(start, j - 1, index_last + 1, len_a - 1))
continue;
path[cur++] = j - 1;
if (IsLess(lstart, lend, start, j - 1) && FindSequence(j , end, start, j - 1, path))
return true;
--cur;
}
return false; //will always find so will never go here
}
//作用同上,反向dp解法,求去掉最小尾数的前面串的最优分割
//返回path的尾座标
int FindSequence(int start, int end, int path[])
{
int c[90]; //反向dp时记录值,存从右向左到当前的首数字最大值,记录例如c[5] = 7 意味者从5-end的最优序列的首元素为a[5:7]
for (int i = end; i >= start; i--) { //对于i:end找一个可能的最大首数字
if (a[i] == '0' && i != end) { //0可以与前面的合并
c[i] = c[i + 1];
continue;
}
if (IsLess(i, end, index_last + 1, len_a -1)) { //结束点,如果当前串整个长度数字仍然小于原串尾数
c[i] = end;
continue;
}
for (int j = end - 1; j >= i; j--) { //动态规划,试探找最大的首数字,子问题也是最优被利用
if (IsLess(i, j, j + 1, c[j + 1])) {
c[i] = j;
break; //ok we have find it ,need to break ,do not forget
}
}
}
//now we will finsh the path 1,23,45,67
//path -1,0,2,4
path[0] = -1;
int i = start; //actually start will always be 0 here
int j = 1;
while (i <= end) {
path[j++] = c[i];
i = c[i] + 1;
}
return j - 1; //since j++ need to - 1
}
bool IsBetterPath() {
for (int i = 0; i < cur && i < cur_best; i++) {
int status = cmp(path_now[i] + 1, path_now[i + 1], path_best[i] + 1, path_best[i + 1]);
if (status == 0) // >
return true;
else if (status == 1) // <
return false;
}
return false; //will not go to here since two path will be different
}
void CopyPath() {
for (int i = 0; i <= cur; i++) {
path_best[i] = path_now[i];
}
}
/* print result */
void PrintData(int start, int end)
{
for (int i = start; i<= end; i++)
cout << a[i];
}
void PrintResult()
{
if (index_last == -1) { //也就是说只有一个数字如 001 或者 21
cout << a << endl;
return;
}
for (int i = 0; i < cur_best; i++) {
PrintData(path_best[i] + 1, path_best[i + 1]);
cout << ",";
}
PrintData(index_last + 1, len_a - 1); //index_last + 1 , len_a - 1
cout << endl;
}
void FinishPath(int path[], int index) {
path[0] = -1;
path[cur] = index;
}
void CalcPath( ) {
len_a = strlen(a);
index_last = -1;
cur = 1; //由于是全局变量,在多次使用时要小心前面的影响 记录path的尾座标
cur_best = 1;
//anlysis string to find last minimal num
FindLast();
//find the sequnece before the last minimal num
FinishPath(path_best, index_last); //1,21 need this
if (index_last >= 1) {
//FindSequence(0, index_last, -1, -1, path_best); //find by rec
//cur_best = cur;
//FinishPath(path_best, index_last);
cur_best = FindSequence(0, index_last, path_best); //find by dp
int tmp_index = index_last;
//由于最后一个数字有可能前面带0,如取83但是前面有0,要考虑到最后数字改取083的情况
//当前的做法是考虑最后数字的所有可能,再此基础上求得前面的path取最优的path,同时
//也就最终确定了最后数字的分割位置index_last可能会向前移动
while (a[tmp_index] == '0') {
if (IsLess(b[tmp_index - 1], tmp_index - 1, index_last + 1, len_a - 1)) {
//cur = 1;
//FindSequence(0, tmp_index - 1, -1, -1, path_now);
//FinishPath(path_now, tmp_index - 1);
cur = FindSequence(0, tmp_index - 1, path_now);
if (IsBetterPath()) {
CopyPath();
cur_best = cur;
index_last = tmp_index - 1;
}
}
tmp_index--;
}
}
}
int main(int argc, char *argv[])
{
while (1) {
cin >> a;
if (a[0] == '0' && a[1] == '\0')
break;
CalcPath();
PrintResult();
}
return 0;
}