package com.leetcode.stringmultiply;
import java.util.Scanner;
public class Main {
// 规模只要在这个范围内可以直接计算(整型数值满足)
private final static int SIZE = 4;
//未经优化,复杂度为o(n^2)
public static String multiply(String num1, String num2) {
if(num1.equals("0")||num2.equals("0"))
return "0";
int length1 = num1.length();
int length2 = num2.length();
StringBuilder sb = new StringBuilder();
int[] array = new int[length1+length2];
//第一位数
for (int i = length1-1; i >= 0; i--) {
//第二位数
for (int j = length2-1; j >= 0; j--) {
int number1 = num1.charAt(i)-'0';
int number2 = num2.charAt(j)-'0';
array[i+j] +=number1*number2;
if(array[i+j] >= 10 && (i+j)!=0) {
array[i + j - 1] += array[i + j] / 10;
array[i + j] = array[i + j] % 10;
}
}
}
// 去掉前导0
int i = 0;
while (i < array.length-1 && array[i] == 0)
i++;
for (; i < array.length-1; i++) {
sb.append(array[i]);
}
return sb.toString();
}
//采用分治的思想做,其中,len为num1、num2的长度最大值
public static String multiply(String num1, String num2, int len) {
String str = "";
//len 少于4位数,可直接计算
if (len <= SIZE) { // 少于4位数,可直接计算
return "" + (Integer.parseInt(num1) * Integer.parseInt(num2));
}
// 长度不同,调用formatNumber方法,补齐X、Y,使之长度相同
if (num1.length() != num2.length()) { // 长度不同,调用formatNumber方法,补齐X、Y,使之长度相同
num1 = formatNumber(num1, len);
num2 = formatNumber(num2, len);
}
// 将num1对半分成两部分、num2对半分成两部分
int len1 = len / 2;
int len2 = len - len1;
String A = num1.substring(0, len1);
String B = num1.substring(len1);
String C = num2.substring(0, len1);
String D = num2.substring(len1);
// 乘法法则,分块处理
int lenM = Math.max(len1, len2);
String AC = multiply(A, C, len1);
String AD = multiply(A, D, lenM);
String BC = multiply(B, C, lenM);
String BD = multiply(B, D, len2);
// 注意处理进位的方法,巧妙地运用了字符串的拼接方面
// 【1】 处理BD,得到原位及进位
String[] sBD = dealString(BD, len2);
// 【2】 处理AD + BC的和
String ADBC = add(AD, BC);
// 【3】 加上BD的进位
if (!"0".equals(sBD[1])) {
ADBC = add(ADBC, sBD[1]);
}
// 【4】 得到ADBC的进位
String[] sADBC = dealString(ADBC, lenM);
// 【5】 AC加上ADBC的进位
AC = add(AC, sADBC[1]);
// 【6】 最终结果
str = AC + sADBC[0] + sBD[0];
return str;
}
// 格式化操作的数字字符串,高位补零
private static String formatNumber(String num, int len) {
while (len > num.length()) {
num = "0" + num;
}
return num;
}
// 两个数字串按位加
private static String add(String ad, String bc) {
// 返回的结果
String str = "";
// 两字符串长度要相同
int lenM = Math.max(ad.length(), bc.length());
ad = formatNumber(ad, lenM);
bc = formatNumber(bc, lenM);
// 按位加,进位存储在flag中
int flag = 0;
// 按序从后往前按位求和
for (int i = lenM - 1; i >= 0; i--) {
int t = flag + Integer.parseInt(ad.substring(i, i + 1))
+ Integer.parseInt(bc.substring(i, i + 1));
// 结果超过9,则进位当前位,保留个位数
if (t > 9) {
flag = 1;
t = t - 10;
} else {
flag = 0;
}
// 拼接结果字符串
str = "" + t + str;
}
if (flag != 0) {
str = "" + flag + str;
}
return str;
}
// 处理数字串,分离出进位,String数组第一个为原位数字,第二个为进位
private static String[] dealString(String ac, int len) {
String[] str = { ac, "0" };
if (len < ac.length()) {
int t = ac.length() - len;
str[0] = ac.substring(t);
str[1] = ac.substring(0, t);
// System.out.println("+++++++++");
// System.out.println(str[0]);
// System.out.println(str[1]);
// System.out.println(t);
} else {
// 保证结果length与len一致,少于则高位补0
String result = str[0];
for (int i = result.length(); i < len; i++) {
result = "0" + result;
}
str[0] = result;
}
return str;
}
public static void main(String[] args) {
Scanner input = new Scanner( System.in);
String num1 = input.nextLine();
String num2 = input.nextLine();
System.out.println(multiply(num1,num2));
int len = Math.max(num1.length(), num2.length());
System.out.println(multiply(num1,num2,len));
}
}