{ }codelper
string lengthreversing stringsP0143

Mark where two lines differ

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
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 k  a = 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;}