Recover Page Numbers
Autumn Tournament (2012)
Submission name: number.cpp
Problem summary
A broken printer concatenates the page number i and the book’s total page count n. Count splits of the digit string into two nonempty decimal numbers satisfying 1≤i≤n. Neither number may have leading zeros.
Input
One digit string.
Output
The number of valid split positions.
Constraints
String length 1–200000.
Worked example
Original statement sample, with whitespace restored where PDF extraction merges adjacent numbers.
Input
23507645
Output
3
Solution analysis
- Never convert the long string into an integer. With no leading zeros, a shorter decimal representation is always smaller, and equal-length representations can be compared lexicographically.
- Let leftLength be the split position and rightLength the remaining length. Reject a split if either number begins with 0. If leftLength<rightLength, accept it; if leftLength>rightLength, reject it. Only an exactly central split can have equal lengths, so a character-by-character comparison is needed at most once.
- For 23507645, the splits after 2 and 23 are valid because the left part is shorter. The split after 235 is invalid because the right part begins with zero. The central split 2350|7645 is valid by lexicographic comparison. All later splits have a longer left part, so the total is three.
Why it works
Every split is considered once. Positive decimal numbers without leading zeros are ordered first by length, then lexicographically when their lengths agree. The accepted splits are therefore exactly those satisfying i≤n.
Watch out. A leading zero on either side is forbidden, including a one-character zero because page numbers must be positive. The two parts must be nonempty. Do not compare different-length numbers lexicographically or use fixed-width integers for the numbers.
Commented C++17 solution
An independently written complete program with standard headers.
#include<iostream>
#include<string>
using namespace std;
int main(){
string digits;
cin>>digits;
int length=static_cast<int>(digits.size());
int answer=0;
if(digits[0]!='0'){
for(int split=1;split<length;++split){
if(digits[split]=='0'){
continue;
}
int rightLength=length-split;
bool valid=split<rightLength;
if(split==rightLength){
// Equal lengths occur only at the central split.
valid=digits.compare(0,split,digits,split,rightLength)<=0;
}
if(valid){
++answer;
}
}
}
cout<<answer<<'\n';
}