Regex 寻找字符串中最短的重复模式
我想知道是否有办法在Octave/matlab中进行模式匹配?我知道Maple 10有这样的命令,但不确定我需要在Octave/Matlab中做什么。因此,如果一个数字是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
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)));