我想知道是否有办法在Octave / matlab中进行模式匹配?我知道Maple 10有命令这样做但不确定我需要在Octave / Matlab中做什么。因此,如果数字为12341234123412341234
,则模式匹配为1234
。我试图找到重复生成整个字符串的最短模式。
请注意:数字(仅使用数字)不会这么简单。另外,我不会提前知道模式(那是我想要找到的)。请参阅下面的Maple 10 example,其中显示该模式未提前知道,但命令会找到模式。
Maple 10模式匹配的示例:
ns:=convert(12341234123412341234,string);
ns := "12341234123412341234"
StringTools:-PrimitiveRoot(ns);
"1234"
如何在Octave / Matlab中执行此操作? Ps:我使用Octave 3.8.1
答案 0 :(得分:10)
要找到重复生成整个字符串的最短模式,可以按如下方式使用正则表达式:
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'
答案 1 :(得分:3)
我不确定这是否可以用正则表达式完成。这是一个脚本,可以在一个名为pattern
的重复单词的情况下执行所需的操作。
它循环遍历名为str
的字符串的字符,尝试匹配另一个名为pattern
的字符串。如果匹配失败,则会根据需要扩展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);
输出结果为:
pattern =
lullaby
注意:强>
这不允许pattern
字符串出现之间的任意分隔符。例如,如果str = 'lullaby1lullaby2lullaby1lullaby2';
,那么
pattern =
lullaby1lullaby2
这也允许pattern
在不改变结果的情况下在一个循环中途结束。例如,str = 'lullaby1lullaby2lullaby1';
仍将导致
pattern =
lullaby1lullaby2
要解决此问题,您可以添加行
if pPtr ~= length(pattern)
pattern = str;
end
答案 2 :(得分:2)
另一种方法如下:
要查找所有可能的因素,请参阅SO上的this解决方案。下一步可以通过多种方式执行,但我在一个简单的循环中实现它,从最小的因子长度开始。
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
答案 3 :(得分:0)
对于您解决问题的方法,此问题是Rorschach的一项很好的测试。我将添加一个信号工程解决方案,该解决方案应该很简单,因为在这种情况下,预计该信号将具有完美的重复性:找到重复时生成整个字符串的最短模式。
在以下传递给函数的str
中,实际上是浮点数的列向量,而不是字符串,原始字符串已用str2num(str2mat(str)')
进行了转换:
function res=findshortestrepel(str);
[~,ii] = max(fft(str-mean(str)));
res = str(1:round(numel(str)/(ii-1)));
我进行了一次小型测试,将其与regexp
解决方案进行比较,发现它总体上更快(蓝色方块),尽管有些不一致,并且仅当您不考虑转换字符串所需的时间时变成浮点向量(绿色方块)。但是,我没有进一步追求这一点(没有打破记录):
以秒为单位的时间。