The first line gives a, and the second line gives b.
We want to show where they differ, with the character columns lined up.
First, compare a and b character by character from the start; let p be the length of the longest run of equal characters there.
Next, remove the first p characters from both a and b, compare the two remaining strings character by character from the end, and let s be the length of the longest run of equal characters there.
So p + s never exceeds the length of the shorter line.
On the first output line print p and s separated by one space.
If a and b are exactly the same, that is all (s is 0 then).
Otherwise print three more lines.
The second line is "- " followed by a, and the third line is "+ " followed by b.
The fourth line is (2 + p) spaces followed by w ^ characters.
w is the larger of the length of the changed part of a (length of a − p − s) and that of b (length of b − p − s).
Input
Each line has length 1 to 1000 and uses only ASCII characters (codes 32 to 126). Neither line starts or ends with a space
Output
one line (when equal) or four lines
Example 1 · stdin
the quick brown fox
the quack brown fox
stdout
6 12
- the quick brown fox
+ the quack brown fox
^
Example 2 · stdin
aa
aaa
stdout
2 0
- aa
+ aaa
^
main.py
Error List00F8 ↓ · ⇧F8 ↑
Input (stdin)
When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).
$ Ready
Open this on a computer to write and run code. On mobile you can read the problem and the solutions.
In other languagesShow solutions by language · 8 languages
There are three traps. First, counting the equal end over the whole strings overlaps with the equal start. For "aa" and "aaa", 2 characters match from the start and 2 from the end of the whole strings, so the changed part has length −2. Count on what remains after removing the first p characters. Second, setting the ^ width from one line only prints no ^ at all for a pure insertion like "print(x)" → "print(x, y)". Third, when the lines are equal, print only the first line. Reversing is Python t[::-1], Java new StringBuilder(t).reverse(), C# Array.Reverse on a char array then new string(c), C++ std::string(t.rbegin(), t.rend()), Craykon t.Reverse(). JS/TS strings have no reverse, so go through an array: [...t].reverse().join(""). In C it is natural not to reverse at all and count from the end with a[la - 1 - s]. Length is Python len(t), JS/TS/Craykon t.length/t.Length, Java t.length(), C# t.Length, C strlen(t), C++ t.size(). C++ size() is unsigned, so if a.size() - p - s went negative it would wrap to a huge number; counting without overlap never goes negative. For string equality only Java needs equals (== asks whether they are the same object).
Pythonmain.py · 18 lines
def common_prefix(x, y): k = 0 while k < len(x) and k < len(y) and x[k] == y[k]: k += 1 return ka = input()b = input()p = common_prefix(a, b)# 앞에서 같은 부분을 뺀 나머지를 뒤집으면, 뒤에서 같은 부분이 앞에서 같은 부분이 된다s = common_prefix(a[p:][::-1], b[p:][::-1])print(p, s)if a != b: print("- " + a) print("+ " + b) width = max(len(a) - p - s, len(b) - p - s) print(" " + " " * p + "^" * width)
JavaScriptmain.js · 19 lines
const [a, b] = require("fs").readFileSync(0, "utf8").split("\n");function commonPrefix(x, y) { let k = 0; while (k < x.length && k < y.length && x[k] === y[k]) k++; return k;}// 문자열에는 reverse가 없어서 배열로 바꿔 뒤집고 다시 잇는다const reverse = (t) => [...t].reverse().join("");const p = commonPrefix(a, b);const s = commonPrefix(reverse(a.slice(p)), reverse(b.slice(p)));const out = [`${p} ${s}`];if (a !== b) { out.push("- " + a, "+ " + b); const width = Math.max(a.length - p - s, b.length - p - s); out.push(" " + " ".repeat(p) + "^".repeat(width));}console.log(out.join("\n"));
TypeScriptmain.ts · 20 lines
import { readFileSync } from "node:fs";const [a, b]: string[] = readFileSync(0, "utf8").split("\n");function commonPrefix(x: string, y: string): number { let k = 0; while (k < x.length && k < y.length && x[k] === y[k]) k++; return k;}// 문자열에는 reverse가 없어서 배열로 바꿔 뒤집고 다시 잇는다const reverse = (t: string): string => [...t].reverse().join("");const p: number = commonPrefix(a, b);const s: number = commonPrefix(reverse(a.slice(p)), reverse(b.slice(p)));const out: string[] = [`${p} ${s}`];if (a !== b) { out.push("- " + a, "+ " + b); const width: number = Math.max(a.length - p - s, b.length - p - s); out.push(" " + " ".repeat(p) + "^".repeat(width));}console.log(out.join("\n"));
JavaMain.java · 31 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main { static int commonPrefix(String x, String y) { int k = 0; while (k < x.length() && k < y.length() && x.charAt(k) == y.charAt(k)) k++; return k; } static String reverse(String t) { return new StringBuilder(t).reverse().toString(); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String a = in.readLine(), b = in.readLine(); int p = commonPrefix(a, b); int s = commonPrefix(reverse(a.substring(p)), reverse(b.substring(p))); StringBuilder out = new StringBuilder(); out.append(p).append(' ').append(s).append('\n'); if (!a.equals(b)) { // == 는 같은 객체인지를 묻는다 out.append("- ").append(a).append('\n'); out.append("+ ").append(b).append('\n'); int width = Math.max(a.length() - p - s, b.length() - p - s); out.append(" ").append(" ".repeat(p)).append("^".repeat(width)).append('\n'); } System.out.print(out); }}
C#Main.cs · 33 lines
using System;class Program{ static int CommonPrefix(string x, string y) { int k = 0; while (k < x.Length && k < y.Length && x[k] == y[k]) k++; return k; } static string Reverse(string t) { char[] c = t.ToCharArray(); Array.Reverse(c); return new string(c); } static void Main() { string a = Console.ReadLine(), b = Console.ReadLine(); int p = CommonPrefix(a, b); int s = CommonPrefix(Reverse(a.Substring(p)), Reverse(b.Substring(p))); Console.WriteLine($"{p} {s}"); if (a != b) { Console.WriteLine("- " + a); Console.WriteLine("+ " + b); int width = Math.Max(a.Length - p - s, b.Length - p - s); Console.WriteLine(" " + new string(' ', p) + new string('^', width)); } }}
C++main.cpp · 25 lines
#include <algorithm>#include <iostream>#include <string>size_t commonPrefix(const std::string& x, const std::string& y) { size_t k = 0; while (k < x.size() && k < y.size() && x[k] == y[k]) k++; return k;}int main() { std::string a, b; std::getline(std::cin, a); std::getline(std::cin, b); size_t p = commonPrefix(a, b); // 앞에서 같은 p글자를 뺀 나머지를 거꾸로(rbegin~rend) 만든다 std::string ra(a.rbegin(), a.rend() - p), rb(b.rbegin(), b.rend() - p); size_t s = commonPrefix(ra, rb); std::cout << p << ' ' << s << '\n'; if (a != b) { std::cout << "- " << a << "\n+ " << b << '\n'; size_t width = std::max(a.size() - p - s, b.size() - p - s); std::cout << " " << std::string(p, ' ') << std::string(width, '^') << '\n'; }}
Cmain.c · 25 lines
#include <stdio.h>#include <string.h>int main(void) { static char a[1100], b[1100]; if (!fgets(a, sizeof a, stdin) || !fgets(b, sizeof b, stdin)) return 0; a[strcspn(a, "\n")] = '\0'; b[strcspn(b, "\n")] = '\0'; int la = (int)strlen(a), lb = (int)strlen(b); int p = 0; while (p < la && p < lb && a[p] == b[p]) p++; /* 뒤집지 않고 끝에서부터 센다. 앞에서 같은 p글자는 다시 세지 않는다 */ int s = 0; while (s < la - p && s < lb - p && a[la - 1 - s] == b[lb - 1 - s]) s++; printf("%d %d\n", p, s); if (strcmp(a, b) != 0) { printf("- %s\n+ %s\n", a, b); int ma = la - p - s, mb = lb - p - s; int width = ma > mb ? ma : mb; printf(" %*s", p, ""); for (int k = 0; k < width; k++) putchar('^'); putchar('\n'); } return 0;}
Craykonmain.cray · 23 lines
a = Console.ReadLine();b = Console.ReadLine();p = commonPrefix(a, b);// 앞에서 같은 부분을 뺀 나머지를 뒤집으면, 뒤에서 같은 부분이 앞에서 같은 부분이 된다s = commonPrefix(a.Substring(p).Reverse(), b.Substring(p).Reverse());Console.WriteLine(p + " " + s);if (a != b){ Console.WriteLine("- " + a); Console.WriteLine("+ " + b); width = Mathf.Max(a.Length - p - s, b.Length - p - s); Console.WriteLine(" " + " ".Repeat(p) + "^".Repeat(width));}commonPrefix(x, y){ k = 0; while (k < x.Length && k < y.Length && x[k] == y[k]) { k += 1; } return k;}