Algorithm 如何从以特殊格式显示的单个字符串创建所有可能的变体?
比方说,我有以下模板Algorithm 如何从以特殊格式显示的单个字符串创建所有可能的变体?,algorithm,parsing,text,Algorithm,Parsing,Text,比方说,我有以下模板 Hello, {I'm|he is} a {notable|famous} person. 结果应该是 Hello, I'm a notable person. Hello, I'm a famous person. Hello, he is a notable person. Hello, he is a famous person. 我想到的唯一可能的解决方案是完全搜索,但它并不有效。 可能有一个很好的算法来做这样的工作,但我不知道是什么任务。数组中的所有置换都非常
Hello, {I'm|he is} a {notable|famous} person.
结果应该是
Hello, I'm a notable person.
Hello, I'm a famous person.
Hello, he is a notable person.
Hello, he is a famous person.
我想到的唯一可能的解决方案是完全搜索,但它并不有效。
可能有一个很好的算法来做这样的工作,但我不知道是什么任务。数组中的所有置换都非常接近于此,但我不知道如何在这里使用它
这里是工作解决方案(它是对象的一部分,所以这里只是相关部分)
generateText()解析字符串并将'Hello,{1 | 2},here{3,4}'
转换为['Hello',['1','2'],'here',['3','4']]]
extractText()接受这个多维数组并创建所有可能的字符串
STATE_TEXT: 'TEXT',
STATE_INSIDE_BRACKETS: 'INSIDE_BRACKETS',
generateText: function(text) {
var result = [];
var state = this.STATE_TEXT;
var length = text.length;
var simpleText = '';
var options = [];
var singleOption = '';
var i = 0;
while (i < length) {
var symbol = text[i];
switch(symbol) {
case '{':
if (state === this.STATE_TEXT) {
simpleText = simpleText.trim();
if (simpleText.length) {
result.push(simpleText);
simpleText = '';
}
state = this.STATE_INSIDE_BRACKETS;
}
break;
case '}':
if (state === this.STATE_INSIDE_BRACKETS) {
singleOption = singleOption.trim();
if (singleOption.length) {
options.push(singleOption);
singleOption = '';
}
if (options.length) {
result.push(options);
options = [];
}
state = this.STATE_TEXT;
}
break;
case '|':
if (state === this.STATE_INSIDE_BRACKETS) {
singleOption = singleOption.trim();
if (singleOption.length) {
options.push(singleOption);
singleOption = '';
}
}
break;
default:
if (state === this.STATE_TEXT) {
simpleText += symbol;
} else if (state === this.STATE_INSIDE_BRACKETS) {
singleOption += symbol;
}
break;
}
i++;
}
return result;
},
extractStrings(generated) {
var lengths = {};
var currents = {};
var permutations = 0;
var length = generated.length;
for (var i = 0; i < length; i++) {
if ($.isArray(generated[i])) {
lengths[i] = generated[i].length;
currents[i] = lengths[i];
permutations += lengths[i];
}
}
var strings = [];
for (var i = 0; i < permutations; i++) {
var string = [];
for (var k = 0; k < length; k++) {
if (typeof lengths[k] === 'undefined') {
string.push(generated[k]);
continue;
}
currents[k] -= 1;
if (currents[k] < 0) {
currents[k] = lengths[k] - 1;
}
string.push(generated[k][currents[k]]);
}
strings.push(string.join(' '));
}
return strings;
},
STATE_TEXT:“TEXT”,
在括号内注明:“括号内”,
generateText:函数(文本){
var结果=[];
var state=this.state\u TEXT;
var length=text.length;
var simpleText='';
var期权=[];
var singleOption='';
var i=0;
while(i
这里的最佳解决方案似乎是n*m
,其中n=第一个数组
和m=第二个数组
。有nm所需的输出线,这意味着只要你只做nm,你就不会做任何额外的工作
如果有2个以上带有选项的数组,则此操作的一般运行时间为
n1*n2…*nm,其中每一个都等于相应列表的大小
一个嵌套循环,您只需打印出外部循环的当前索引值和内部循环的当前索引值,就可以正确地执行此操作
我想到的唯一可能的解决方案是完全搜索,但它并不有效
如果必须提供完整结果,则必须运行完整搜索。根本没有办法解决这个问题。不过,您不需要所有排列:结果的数量等于每个模板中备选方案数量的乘积
Hello, {I'm|he is} a {notable|famous} person.
尽管有多种实现方法,但递归是最流行的方法之一。下面是一些让您开始使用的伪代码:
string[][] templates = {{"I'm", "he is"}, {"notable", "famous", "boring"}}
int[] pos = new int[templates.Length]
string[] fills = new string[templates.Length]
recurse(templates, fills, 0)
...
void recurse(string[][] templates, string[] fills, int pos) {
if (pos == fills.Length) {
formatResult(fills);
} else {
foreach option in templates[pos] {
fills[pos] = option
recurse(templates, fills, pos+1);
}
}
}
这取决于具体的用例。这些模板是预定义的还是以某种方式受到限制的。您是只搜索一个“小”文本,还是有多个文本单元可供搜索。这些文本经常变化还是很少变化……。可以有许多行,每行可以有数千个{a | b | c}模板(以及其他一些shell)内置rhis功能,尽管您需要使用
,
而不是|
来分离备选方案,并且还需要一些引用。例如,尝试使用printf“%s\n””你好,“{”我“,”他“}”是一个“{著名的}”人。