Regex 寻找字符串中最短的重复模式

Regex 寻找字符串中最短的重复模式,regex,matlab,pattern-matching,octave,maple,Regex,Matlab,Pattern Matching,Octave,Maple,我想知道是否有办法在Octave/matlab中进行模式匹配?我知道Maple 10有这样的命令,但不确定我需要在Octave/Matlab中做什么。因此,如果一个数字是123412341234123411234,那么模式匹配将是1234。我试图找到最短的模式,在重复时生成整个字符串 请注意:数字(只使用数字)不会这么简单。而且,我不会提前知道模式(这就是我试图找到的)。请参阅下面的说明,该模式在时间之前是未知的,但是命令会找到该模式 Maple 10模式匹配示例: ns:=convert(12

我想知道是否有办法在Octave/matlab中进行模式匹配?我知道Maple 10有这样的命令,但不确定我需要在Octave/Matlab中做什么。因此,如果一个数字是
123412341234123411234
,那么模式匹配将是
1234
。我试图找到最短的模式,在重复时生成整个字符串

请注意:数字(只使用数字)不会这么简单。而且,我不会提前知道模式(这就是我试图找到的)。请参阅下面的说明,该模式在时间之前是未知的,但是命令会找到该模式

Maple 10模式匹配示例:

ns:=convert(12341234123412341234,string);

             ns := "12341234123412341234"

StringTools:-PrimitiveRoot(ns);

             "1234"
如何在倍频程/Matlab中实现这一点?
Ps:我使用的是Octave 3.8.1

我不确定这是否可以通过正则表达式实现。下面是一个脚本,它可以在重复出现名为
pattern
的单词时执行所需的操作

它在名为
str
的字符串中循环,试图与另一个名为
pattern
的字符串匹配。如果匹配失败,则根据需要扩展
模式
字符串

编辑:我使代码更加紧凑

str = 'lullabylullabylullaby';

pattern = str(1);
matchingState = false;
sPtr = 1;
pPtr = 1;

while sPtr <= length(str)
     if str(sPtr) == pattern(pPtr) %// if match succeeds, keep looping through pattern string
            matchingState = true;
            pPtr = pPtr + 1;
            pPtr = mod(pPtr-1,length(pattern)) + 1;
     else                          %// if match fails, extend pattern string and start again
            if matchingState
                sPtr = sPtr - 1;   %// don't change str index when transitioning out of matching state
            end  
            matchingState = false;
            pattern = str(1:sPtr);
            pPtr = 1;
     end

     sPtr = sPtr + 1;

end

display(pattern);

注意:

这不允许在出现的
模式
字符串之间使用任意分隔符。例如,如果
str='lulllaby1lulllaby2lulllaby1lulllaby2',然后

pattern =

lullaby1lullaby2
这也允许
模式
在循环中途结束,而不改变结果。例如,
str='lulllaby1lulllaby2lulllaby1'仍将导致

pattern =

lullaby1lullaby2
要解决此问题,可以添加行

if pPtr ~= length(pattern)
    pattern = str;
end

要找到重复生成整个字符串的最短模式,可以使用正则表达式,如下所示:

result = regexp(str, '^(.+?)(?=\1*$)', 'match');
一些例子:

>> str = '12341234123412341234';
>> result = regexp(str, '^(.+?)(?=\1*$)', 'match')
result = 
    '1234'

>> str = '1234123412341234123';
>> result = regexp(str, '^(.+?)(?=\1*$)', 'match')
result = 
    '1234123412341234123'

>> str = 'lullabylullaby';
>> result = regexp(str, '^(.+?)(?=\1*$)', 'match')
result = 
    'lullaby'

>> str = 'lullaby1lullaby2lullaby1lullaby2';
>> result = regexp(str, '^(.+?)(?=\1*$)', 'match')
result = 
    'lullaby1lullaby2'

另一种方法如下:

  • 确定字符串的长度,并找到字符串长度值的所有可能因素
  • 对于每个可能的因子长度,重塑字符串并检查 对于重复的子字符串
  • 要找到所有可能的因素,请参见下面的解决方案。下一步可以通过多种方式执行,但我在一个简单的循环中实现它,从最小的因子长度开始

    function repeat = repeats_in_string(str);
    ns = numel(str);
    nf = find(rem(ns, 1:ns) == 0);
    for ii=1:numel(nf)
        repeat = str(1:nf(ii));
        if all(ismember(reshape(str,nf(ii),[])',repeat)); 
            break;
        end
    end 
    

    这个问题对于你解决问题的方法来说是一个很好的罗夏测验。我将添加一个信号工程解决方案,该解决方案应该很简单,因为信号应该是完全重复的,假设这一点成立:找到在重复时生成整个字符串的最短模式

    在下面的
    str
    中,提供给函数的实际上是浮点的列向量,而不是字符串,原始字符串已通过
    str2num(str2mat(str)')
    转换:

    我执行了一个小测试,将其与 ReGeXP</Cl>解决方案进行比较,发现它的整体速度更快(蓝色正方形),虽然有些不一致,但仅当不考虑将字符串转换为浮标向量时所需的时间(绿色正方形)。但是,我没有进一步研究这一点(没有打破这方面的记录):


    以秒为单位的时间。

    没有人会查找Maple示例。请在问题中提供相关信息。例如,您应该添加命令应该为您查找模式…模式的长度已知且固定吗?输入字符串是否只包含模式或其他字符?我的问题是:字符串是否为
    1234912348123471234612345
    ,并且需要查找的模式是否为
    1234
    ?嗯,还不清楚。如果可能有多个模式,您希望检测哪一个:最长的一个?发生率最高的模式是什么?那么最小长度是多少?想象一下
    123412341123412341123
    你会发现
    1234
    四次,但是
    123
    五次,实际上
    123412341123
    也是一种模式。请提供一个更好的示例,它涵盖了所有特殊情况。但最长的“1234123411234123411234”模式可能是“1234123411234123411234”,第二长的模式是“12341234112341234123”-因此,如果您说明实际输入没有示例那么简单,请发布您的真实输入:)@eigenchris我也是:-)我所有关于
    regexp
    的答案都应该归功于!顺便说一句,我借用了你的例子,
    str='1234123512341234512351234'的结果是什么不是
    '1234
    ?关于我的一个评论,应该是这样的。我真的不明白那个问题。我真的很努力。我认为虽然OP的问题陈述模棱两可,但这可能是他们想要的答案。它符合相当于Maple命令的规格。@LuisMendo我们真的应该引入精神主义者奖;)OP再次冲击我们的心灵,让我们困惑。。。。从所有这些混乱的灰烬中诞生了一位精神主义者,他的唯一目的是消除这个世界上的混乱。其他几个是从这个事件中产生的,因此创造了。。。精神主义者联盟。去吧,精神主义者去吧!你在用什么编程语言?@Jan这是MATLAB,一种主要由工程师和科学家用于数值计算的语言。接受的解决方案比使用大多数语言支持的正则表达式要好得多。谢谢。很难找到关于这种语言的好文档。我正试图把它转换成C。“pattern=str(1);”和“pattern=str(1:sPtr);”以及“if-str(sPtr)=pattern(pPtr)”这两行到底是做什么的?我把它改成了resp。“字符串模式=s.Substring(0,1);”,“模式=s.Substring(0,sPtr);”和“如果(s.Substring(sPtr)==pattern.Substring(pPtr))”。我还注意到Matlab字符串在C#中是基于1的,而不是基于0的。Jan看起来您已经或多或少正确地转换了代码。如果你正在努力解决这个问题,我建议你提出一个新问题。同样,用于在文本中搜索模式
    function repeat = repeats_in_string(str);
    ns = numel(str);
    nf = find(rem(ns, 1:ns) == 0);
    for ii=1:numel(nf)
        repeat = str(1:nf(ii));
        if all(ismember(reshape(str,nf(ii),[])',repeat)); 
            break;
        end
    end 
    
    function res=findshortestrepel(str);
    [~,ii] = max(fft(str-mean(str)));
    res = str(1:round(numel(str)/(ii-1)));