Tìm chuỗi gốc, không lặp lại mà không lặp lại ở giữa


25

Đôi khi điều đó xảy ra khi gõ một câu, tôi bị phân tâm và cuối cùng tôi gõ cùng một vài từ hai lần hai từ hai lần liên tiếp.

Để đảm bảo người khác không bị làm phiền bởi điều này, nhiệm vụ của bạn là viết một chương trình giải quyết vấn đề này!

Bài tập

Đưa ra một chuỗi đầu vào (nếu nó quan trọng đối với ngôn ngữ của bạn, bạn có thể giả sử đầu vào chỉ ASCII không chứa nguồn cấp dữ liệu.) str, Có chứa một chuỗi ở giữa một chuỗi con xảy ra hai lần liên tiếp, trả về chuỗi với một thể hiện này loại bỏ chuỗi con.

Trong trường hợp có nhiều khả năng, hãy trả về câu trả lời ngắn nhất có thể (nghĩa là chọn chuỗi con lặp lại liên tiếp dài nhất và loại bỏ chuỗi đó).

Trong trường hợp nhiều chuỗi con lặp lại liên tiếp dài bằng nhau, hãy loại bỏ chuỗi đầu tiên (nghĩa là lần đầu tiên gặp phải khi đọc qua chuỗi từ trước ra sau).

Bạn có thể cho rằng đầu vào là chính xác (nghĩa là luôn chứa một chuỗi con lặp lại liên tiếp), điều này có thể giúp đánh bại nó.


Ví dụ

  1. Đầu vào: hello hello world-> Đầu ra : hello world.
  2. Đầu vào: foofoo-> Đầu ra : foo. (Vì vậy: Có, chuỗi có thể chỉ bao gồm phần lặp lại hai lần).
  3. Đầu vào: aaaaa-> Đầu ra : aaa, vì chuỗi con liên tiếp lặp lại dài nhất ở đây aa.
  4. Đầu vào: Slartibartfast-> Đây không phải là đầu vào hợp lệ, vì nó không chứa chuỗi con lặp lại liên tiếp, vì vậy bạn không cần phải xử lý trường hợp này.
  5. Đầu vào: the few the bar-> Đây là một đầu vào không hợp lệ khác, vì phần lặp lại sẽ ngay lập tức theo phần gốc. Trong trường hợp này thetheđược phân tách bằng một cái gì đó khác ở giữa, vì vậy đầu vào này không hợp lệ.
  6. Đầu vào: ababcbc-> Đầu ra : abcbc. Hai chuỗi con lặp lại liên tiếp dài nhất có thể là abbc. Như đã abgặp trước đó trong chuỗi, đây là câu trả lời đúng.
  7. Đầu vào : Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. Đầu ra : Buffalo buffalo buffalo buffalo Buffalo buffalo. (Việc thay thế được thực hiện phải phân biệt chữ hoa chữ thường).
  8. Đầu vào: Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.-> Đầu ra : Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Chỉ có chuỗi con lặp lại liên tiếp dài nhất được loại bỏ.

Mã của bạn phải càng ngắn càng tốt, vì đây là , vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng. Chúc may mắn!


@manatwork Khi lấy câu đầu tiên, đó là Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.đầu vào, đầu ra phải là Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Chỉ có sự trùng lặp dài nhất được tìm thấy được loại bỏ.
Qqwy

1
Tôi đề nghị thêm một bài kiểm tra có hai lần thay thế có thể, trong đó bài kiểm tra thứ hai dài hơn bài kiểm tra thứ nhất. Tôi nghi ngờ hầu hết các câu trả lời sẽ không vượt qua câu trả lời đó :)
qua

@aross test case 8 chính xác là như vậy :)
Qqwy

Trừ khi tôi và mã kiểm tra của tôi bị nhầm, chỉ có một chuỗi lặp lại ở đó.
vào

@aross có một cú đúp ptronghappens
Qqwy

Câu trả lời:


8

Perl 6 , 40 byte

{.subst: m:ex/(.*))>$0/.max(*.chars),''}

Thử nó

{
  .subst:             # substitute


    m                 # match
    :exhaustive
    /
      ( .* )          # any number of chars

      )>              # don't include the following in what is returned

      $0              # the first match again
    /.max( *.chars ), # find the first longest submatch


    ''                # substitute it with nothing
}

8

Võng mạc , 35 33 byte

Số lượng byte giả định mã hóa ISO 8859-1.

(?=(.+)(\1.*))
$2¶$`
O$#`
$.&
G1`

Hãy thử trực tuyến!

Giải trình

Vì các công cụ regex tìm kiếm các trận đấu từ trái sang phải, nên việc tìm trận đấu dài nhất không phụ thuộc vào vị trí. Nó có thể được thực hiện với các nhóm cân bằng của .NET, nhưng kết quả khá dài một cách khó chịu:

1`((.)+)\1(?<=(?!.*((?>(?<-2>.)+).+)\3)^.*)
$1

Vì vậy, tôi nghĩ rằng tôi sẽ cố gắng tránh điều đó bằng cách sử dụng một số tính năng Retina khác.

(?=(.+)(\1.*))
$2¶$`

Chúng tôi bắt đầu bằng cách áp dụng tất cả các thay thế có thể, một trên mỗi dòng. Để làm điều này, chúng tôi khớp vị trí trước một trận đấu (thay vì chính trận đấu), để cho phép các trận đấu chồng chéo. Điều này được thực hiện bằng cách đặt regex thực sự vào một cái nhìn. Cái nhìn đó sau đó nắm bắt phần còn lại ngoại trừ bản sao mà chúng tôi muốn xóa trong nhóm 2. Chúng tôi viết lại nhóm 2 (xóa bản sao), một nguồn cấp dữ liệu, sau đó toàn bộ đầu vào cho đến khớp, về cơ bản cho chúng tôi một dòng mới được thay thế.

Cuối cùng, chúng tôi sẽ có một dòng cho mỗi trận đấu, với loại bỏ trùng lặp tương ứng. Cuối cùng, cũng sẽ có đầy đủ đầu vào một lần nữa mà không có sự thay thế nào được thực hiện.

Bây giờ chúng tôi có tất cả các thay thế có thể, chúng tôi muốn kết quả ngắn nhất (tương ứng với sự lặp lại bị loại bỏ lâu nhất).

O$#`
$.&

Vì vậy, trước tiên chúng tôi sắp xếp các dòng theo chiều dài.

G1`

Và sau đó chúng tôi chỉ giữ dòng đầu tiên.


Wow, kỹ thuật thay thế đó thực sự thông minh!
Leo

6

Thạch , 22 19 byte

-2 byte nhờ Dennis (tránh đảo ngược đối số, loại bỏ gia tăng dư thừa một cách tinh tế)

ẋ2³wȧ+¥J
ẆÇ€LÐṀḢṬœp

Hãy thử trực tuyến!

Toàn bộ chương trình (một lỗi đã được tìm thấy khi ÐṀkhông hoạt động với mức độ chính xác so với dyads, sẽ được khắc phục sớm; mặc dù tôi không chắc nó có thể tạo mã ngắn hơn ở đây không).

Làm sao?

Tìm những lát đầu tiên dài nhất của đầu vào sao cho sự lặp lại tồn tại trong đầu vào và loại bỏ nó khỏi đầu vào.

ẋ2³wȧ+¥J - Link 1, removal indices for given slice if valid, else 0: slice, x
ẋ2       - repeat x twice, say y
  ³      - program input: s
   w     - index of first occurrence of y in s (1-based) or 0, say i
       J - range(length(x)): [1,2,3,...,length(x)]
      ¥  - last two links as a dyad
    ȧ    -     and (non-vectorising)
     +   -     addition: [1+i,2+i,3+i,...,length(x)+i] or 0
         - note: no need to decrement these since the last index will be the 1st index
         - of the repetition (thanks to Dennis for spotting that!)

ẆÇ€LÐṀḢṬœp - Main link: string, s
Ẇ          - all sublists of s (order is short to long, left to right, e.g. a,b,c,ab,bc,abc)
 Ç€        - call the last link (1) as a monad for €ach
    ÐṀ     - filter by maximal
   L       -     length
      Ḣ    - head: get the first (and hence left-most) one
       Ṭ   - untruth: make a list with 1s at the indexes given and 0s elsewhere
        œp - partition s at truthy indexes of that, throwing away the borders
           - implicit print

6

JavaScript (ES6), 81 74 byte

f=
s=>s.replace(/(?=(.+)\1)/g,(_,m)=>r=m[r.length]?m:r,r='')&&s.replace(r,'')
<input oninput=o.textContent=f(this.value)><pre id=o>

Chỉnh sửa: Đã lưu 7 byte bằng cách ăn cắp m[r.length]thủ thuật của @ Arnauld .


5

PowerShell , 87 byte

param($s)([regex](([regex]'(.+)\1'|% *hes $s|sort L*)[-1]|% Gr*|% V*)[1])|% Re* $s '' 1

Hãy thử trực tuyến! (tất cả các trường hợp thử nghiệm)

Giải trình

Bắt đầu từ bên trong về cơ bản, chúng tôi chạy Matchesvới (.+)\1regex, để trả về tất cả các đối tượng khớp cho chuỗi đã chỉ định. Regex phù hợp với bất kỳ chuỗi ký tự nào được theo sau bởi chính nó.

Sau đó, các đối tượng khớp kết quả được dẫn vào sortđể được sắp xếp theo thuộc tính của chúng Length(rút ngắn thành ký tự đại diện). Điều này dẫn đến một loạt các kết quả khớp được sắp xếp theo chiều dài, tăng dần, do đó chỉ mục [-1]để có được phần tử cuối cùng (dài nhất). Giá trị của trận đấu đó là khớp, mặc dù không phải là nhóm, do đó, nó bao gồm sự lặp lại, vì vậy chúng tôi truy xuất đối tượng Nhóm ( |% Gr*) và sau đó là giá trị của ( |% V*) đó để có được chuỗi lặp lại lớn nhất. Điều là đối tượng nhóm thực sự là một mảng vì nhóm 0 luôn luôn khớp, nhưng tôi muốn nhóm thực tế (1), vì vậy giá trị kết quả thực sự là giá trị s , do đó lập chỉ mục để có được phần tử thứ hai [1]. Giá trị này được truyền tới một đối tượng regex và sau đóReplacephương thức được gọi ngược với chuỗi gốc, thay thế bằng không có gì và chỉ có kết quả khớp đầu tiên được thay thế ( |% Re* $s '' 1).


5

Haskell , 101 byte

Chức năng chính là f, nó mất và trả về a String.

l=length
a=splitAt
f s|i<-[0..l s-1]=[p++t|n<-i,(p,(r,t))<-fmap(a$l s-n).(`a`s)<$>i,r==take(l r)t]!!0

Hãy thử trực tuyến!

Khi tôi bắt đầu này, tôi nhập khẩu Data.Listvà sử dụng maximum, tails, initsisPrefixOf. Bằng cách nào đó đã biến thành thế này. Nhưng tôi vẫn chỉ có thể cạo được 11 byte ...

Ghi chú

  • splitAt/ atách một chuỗi tại một chỉ mục nhất định.
  • s là chuỗi đầu vào.
  • ilà danh sách các số [0 .. length s - 1], nghĩa -1là làm việc xung quanh splitAtphân tách ở cuối nếu được cung cấp một chỉ số quá lớn.
  • nlength strừ mục tiêu độ dài hiện tại cho phần lặp lại, nó được chọn theo cách đó vì vậy chúng tôi không phải sử dụng hai danh sách số và / hoặc cú pháp danh sách giảm chi tiết.
  • p, rtlà một phân chia ba chiều s, với rphần lặp lại dự định. Ở fmapđó sử dụng (,) String Functorđể tránh một biến cho một phân chia trung gian.
  • !!0 chọn thành phần đầu tiên của danh sách các trận đấu.


4

Toán học, 63 60 59 byte

4 byte được lưu do Martin Ender .

#&@@StringReplaceList[#,a__~~a__->a]~SortBy~{StringLength}&

Chức năng ẩn danh. Lấy một chuỗi làm đầu vào và trả về một chuỗi là đầu ra.


Điều này dường như không hoạt động trên ví dụ 6 - ~SortBy~StringLengthsắp xếp các chuỗi theo thứ tự bảng chữ cái nếu độ dài của chúng giống nhau ...
Không phải là một cây

1
@ LegionMammal978 Bản sửa lỗi ngắn hơn được giữ SortByvà bọc StringLengthtrong một danh sách để có được một loại ổn định.
Martin Ender

3

JavaScript (ES6), 70 byte

s=>s.replace(s.match(/(.+)(?=\1)/g).reduce((p,c)=>c[p.length]?c:p),'')

Các trường hợp thử nghiệm


Thất bại trên aaaabaaab, nhưng sử dụng tốt đẹp reduce.
Neil

2

Đây phải là một bình luận, nhưng tôi không có đủ danh tiếng để bình luận. Tôi chỉ muốn nói với @Neil rằng mã của anh ta có thể giảm xuống còn 77 byte. Bạn không cần phải sử dụng xác nhận chuyển tiếp trong regex. Đây là phiên bản rút gọn:

s=>s.replace(/(.+)\1/g,(_,m)=>(n=m.length)>l&&(l=n,r=m),l=0)&&s.replace(r,'')

2
Xin chào, và chào mừng đến với PPCG! Bạn có thể gửi câu hỏi này dưới dạng câu trả lời JavaScript của riêng bạn! Nếu bạn thích, tôi có thể chỉnh sửa bài đăng của bạn và cho bạn thấy nó nên trông như thế nào.
NoOneIsHãy

2
Tôi cần sử dụng xác nhận chuyển tiếp để đối phó với trường hợp trùng khớp. aabablà ví dụ ngắn nhất về đề xuất của bạn thất bại.
Neil

0

C #, 169 byte

(s)=>{var x="";for(int i=0;i<s.Length-2;i++){for(int l=1;l<=(s.Length-i)/2;l++){var y=s.Substring(i,l);if(s.Contains(y+y)&l>x.Length)x=y;}}return s.Replace(x+x,x);}

Giải trình

(s) => {                // Anonymous function declaration    
    var x = "";         // String to store the longest repeating substring found
    for (int i = 0; i < s.Length - 2; i++) {               // Loop through the input string
        for (int l = 1; l <= (s.Length - i) / 2; l++) {    // Loop through all possible substring lengths
            var y = s.Substring(i, l);
            if (s.Contains(y + y) & l > x.Length) x = y;   // Check if the substring repeats and is longer than any previously found
        }
    }
    return s.Replace(x + x, x);    // Perform the replacement
}

Đây là cách tiếp cận brute-force: thử mọi chuỗi con có thể cho đến khi chúng ta tìm thấy chuỗi con lặp lại dài nhất. Không nghi ngờ gì nữa, Regex hiệu quả hơn, nhưng giao dịch với Regex trong C # có xu hướng khá dài dòng.


Chào mừng đến với PPCG! Tất cả các câu trả lời cần phải là chương trình đầy đủ hoặc các hàm có thể gọi được , không chắc chắn các đoạn có đầu vào trong các biến được mã hóa cứng. Ngoài ra, vui lòng hiển thị phiên bản mã mà bạn thực sự đã tính với tất cả các khoảng trắng không cần thiết bị xóa. Bạn luôn có thể bao gồm phiên bản dễ đọc hơn với thụt lề ngoài phiên bản được đánh gôn hoàn toàn.
Martin Ender

0

PHP, 84 82 byte

Lưu ý: sử dụng mã hóa IBM-850.

for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;

Chạy như thế này:

echo 'hello hello world' | php -nR 'for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;';echo
> hello world

Giải trình

for(
  $l=strlen($argn);   # Set $l to input length.
  --$l   &&           # Decrement $l each iteration until it becomes 0.
  !$r=preg_filter(    # Stop looping when preg_filter has a result
                      # (meaning a successful replace).
    "#(.{0$l})\g-1#", # Find any character, $l times (so the longest
                      # match is tried first), repeated twice.
    ~█╬,              # Replace with $1: first capture group, removing the
                      # duplicate.
    $argn,
    1                 # Only replace 1 match.
  );
);
echo$r;               # Print the result of the (only) successful
                      # search/replace, if any.

Tinh chỉnh

  • Đã lưu 2 byte vì không có độ dài tối thiểu của chuỗi con lặp lại
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.