共产子串标准化


13

如果长度为K的字符串T在字符串S中出现K次或多次,则有潜在的共性。例如,in 可能是共通的,因为它出现2次且长度为2。请注意,这些子字符串不能重叠。1010/10

共产变换是一个取该字符串Ť和移动每个字符Ť的发生Ť小号。因此,对于前面的示例,共产主义转化会产生1/0;第一次找到10替换10的第一个字符,第二次找到。100

共产正常化是一个函数,它的所有这样的串Ťķ ≥2并执行共产变换他们。

该算法的一些细节:

  1. 首先对最长的有效字符串T 执行公共转换。支持T的第一次出现。
  2. 然后,对下一个最长的字符串执行共性转换,然后对下一个最长的字符串进行等等。
  3. 重复直到字符串中不存在这样的字符串。

注意,可以用两种不同的方式来解释一些字符串,例如测试用例中的“ Hello,Hello”示例。您可以使用ell牛逼,但你也可以使用llo。在这种情况下,您的代码可以选择任何一个。所示的测试用例使用llo,但是您可能会获得不同且有效的输出。


您的任务是实现社区标准化。输入将仅包含可打印的ASCII字符(0x20至0x7E,空格至波浪号)。您可以编写程序或函数来解决此任务;输入可以当作来自STDIN的一行,字符串/字符数组参数,来自ARGV的参数等。

测试用例

'123' -> '123'
'111' -> '111'
'1111' -> '11'
'ABAB' -> 'AB'
'111111111' -> '111'
'asdasdasd' -> 'asd'
'10/10' -> '1/0'
'100/100+100' -> '1/0+0'
'   +   +   ' -> ' + '
'Hello, hello, dear fellow!' -> 'Hel he, dear feow!' OR 'Heo hl, dear flow!'
'11122333/11122333/11122333' -> '112/13' OR '132/23'

'ababab1ababab' -> 'a1bab'
'1ab2ab3ab4ab5ab6' -> '1a2b3a4b5ab6'

制定测试用例

'string', 'substring'在替换的每个步骤中,格式为。替换的位放在方括号中。

'11[122]333/11[122]333/11[122]333', '122'
'111[333]/112[333]/112[333]', '333'
'1113/11[23]/11[23]', '23'
'11[13]/112/1[13]', '13'
'1[11]/[11]2/13', '11'
'1[/1]12[/1]3', '/1'
'112/13', ''

另一个测试用例:

'Hello, hello, dear fellow!', 'llo'
'Hel, hel, dear feow!', 'l,'
'Hel he, dear feow!', ''

参考代码(Python)

您可能会发现这对可视化算法很有用。

#!/usr/bin/env python

import re

def repeater(string):
    def repeating_substring(substring):
        return (string.count(substring) == len(substring)) and string.count(substring) > 1

    return repeating_substring

def get_substrings(string):
    j = 1
    a = set()
    while True:
        for i in range(len(string) - j+1):
            a.add(string[i:i+j])
        if j == len(string):
            break
        j += 1
    return list(a)

def replace_each_instance(string, substring):
    assert `string`+',', `substring`
    for i in substring:
        string = re.sub(re.escape(substring), i, string, 1)

    return string


def main(s):
    repeats = repeater(s)
    repeating_substr = filter(repeater(s), get_substrings(s))

    while repeating_substr:
        repeating_substr.sort(lambda x,y: cmp(len(y), len(x)))
        s = replace_each_instance(s, repeating_substr[0])
        repeating_substr = filter(repeater(s), get_substrings(s))

    return s

assert main('123') == '123'
assert main('111') == '111'
assert main('1111') == '11'
assert main('ABAB') == 'AB'
assert main('111111111') == '111'
assert main('asdasdasd') == 'asd'
assert main('10/10') == '1/0'
assert main('100/100+100') == '1/0+0'
assert main('   +   +   ') == ' + '
assert main('Hello, hello, dear fellow!') == 'Hel he, dear feow!'
assert main('11122333/11122333/11122333') == '112/13'

感谢@ ConorO'Brien发布了此挑战的初衷。


测试用例:ababab1ababab1ab2ab3ab4ab5ab6
Zgarb

为什么没有变化?ab在两个字符串中至少出现两次。
Zgarb

@Zgarb看起来我的测试仪很糟糕,我稍后将对其进行修复。虽然手动修复测试用例。
Rɪᴋᴇʀ

Answers:


2

Pyth,22个字节

u.xse.iLcGdf>cGTlTt#.:

测试套件

要实际查看程序在做什么,请查看以下内容:

内部构造

特别是,程序始终使用最长替换的最后一次替换。

说明:

u.xse.iLcGdf>cGTlTt#.:
u.xse.iLcGdf>cGTlTt#.:G)GQ    Implicit
u                        Q    Starting with the input, repeat the following
                              until a fixed point is reached.
                    .:G)      Construct all substrings of the current value
                              ordered smallest to largest, front to back.
                  t#          Filter on having more than 1 element.
                              These are the eligible substrings.
           f                  Filter these substrings on
             cGT              Chop the current value on the substring,
            >   lT            Then remove the first len(substring) pieces.
                              The result is nonempty if the substring is
                              one we're looking for. 
                              Chopping gives nonoverlapping occurrences.
     .iL                      Interlace the substrings with
        cGd                   Chop the current value on that substring
   se                         Take the final result, make it a string.
 .x                     G     If there weren't any, the above throws an error,
                              So keep the current value to halt.

4

JavaScript(ES6),121个字节

f=(s,j=2,o,m=s.match(`(.{${j}})(.*\\1){${(j-1)}}`))=>m?f(s,j+1,s.split(m[1]).map((e,i)=>e+(m[1][i]||'')).join``):o?f(o):s

递归匹配模式:

(.{2})(.*\1){1}  //2 characters, repeated 1 time 
(.{3})(.*\1){2}  //3 characters, repeated 2 times 
(.{4})(.*\1){3}  //4 characters, repeated 3 times 
etc.

…直到找不到模式。(这保证了最长的字符串将首先被处理。)

然后,通过在比赛中进行分割并加入比赛中的每个角色,对最后找到的模式执行“社区转化”。(map用于此目的。可惜的join是不接受回调。)

最终,它将在此新字符串上重复进行,直到不再具有共性

测试用例:


1

干净420个 ... 368个字节

import StdEnv,StdLib
l=length
%q=any((==)q)
?_[]=[]
?a[(y,x):b]|isPrefixOf a[x:map snd b]=[y: ?a(drop(l a-1)b)]= ?a b
$s=sortBy(\a b=l a>l b)(flatten[[b: $a]\\(a,b)<-map((flip splitAt)s)[0..l s-1]])
f s#i=zip2[0..]s
#r=filter(\b=l(?b i)>=l b&&l b>1)($s)
|r>[]#h=hd r
#t=take(l h)(?h i)
=f[if(%n t)(h!!hd(elemIndices n t))c\\(n,c)<-i|not(%n[u+v\\u<-t,v<-[1..l h-1]])]=s

在线尝试!


该答案无效。看这里。应该进行更改,请参见测试用例。
Rɪᴋᴇʀ

@Riker很有趣,因为它是参考解决方案的直接端口。我将删除它,直到修复为止。
世纪

@Riker现在已修复。
Οurous
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.