When setting up the two regressions, R treats them differently. In the first (with intercept) case, it takes the first factor and re-frames it as a smaller number of factors, each representing the difference between a level and the first level (so there are 2 coefficients to estimate in your case instead of 3.) This avoids the multicollinearity that would be caused by the "full" representation + an intercept. It then does the same for the second. Hence you get an intercept and 3 total coefficients.
In the second case, it knows there isn't an intercept, so it doesn't re-frame the first factor, instead leaving it as is. It still re-frames the second factor, though, to avoid the multicollinearity.
Here's your example; we can look at the coefficient values to see what's happening:
x1=factor(rep(1:3, 100))
x2=factor(rep(1:2, 150))
y=rnorm(300)
summary(lm(y~x1+x2+1))
... stuff ...
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.13537 0.11742 1.153 0.2499
x12 -0.20787 0.14381 -1.445 0.1494
x13 -0.28883 0.14381 -2.008 0.0455 *
x22 0.05656 0.11742 0.482 0.6304
---
summary(lm(y~x1+x2-1))
... stuff removed ...
Coefficients:
Estimate Std. Error t value Pr(>|t|)
x11 0.13537 0.11742 1.153 0.250
x12 -0.07250 0.11742 -0.617 0.537
x13 -0.15346 0.11742 -1.307 0.192
x22 0.05656 0.11742 0.482 0.630
You can see that the Intercept in the first regression has the same value as x11 in the second. x12 in the first equals x12-x11 in the second, and x13 in the first equals x13-x11 in the second, both as a consequence of representing the factors as differences in the first regression. x22 is the same in both, because including all the levels of the second factor will result in multicollinearity in both regressions.