【发布时间】:2014-11-15 17:26:18
【问题描述】:
让我们有一个数字序列。说 {1, 2, 3, 4, 5}。以及一组带权重的子序列替换。例如:
{1} -> {3} : 0.2 - 女巫意味着 1 可以被 3 替换,权重为 0.1
{2, 3, 4} -> {4, 3} : 0.3
{5} -> {2} : 0.4
我需要找到使用限制权重的替换可以得到的所有序列。
限制如下:任何 n (3) 个项目(连续)的替换权重总和应小于给定数字 e
对于我们的示例,结果是:
{1, 2, 3, 4, 5} :替换权重:{0, 0, 0, 0, 0}。连续任意 3 项之和小于 0.5
{3, 2, 3, 4, 5}:替换权重:{0.2, 0, 0, 0, 0}
{1, 4, 3, 5} :替换权重:{0, 0.3/3, 0.3/3, 0.3/3, 0} 3 个符号的序列所以 /3
{3, 4, 3, 5} 替换权重:{0.2, 0.3/3, 0.3/3, 0.3/3, 0}
{1, 2, 3, 4, 2} 替换权重:{0, 0, 0, 0, 0.4}
{3, 2, 3, 4, 2} 替换权重:{0.2, 0, 0, 0, 0.4}
我们不允许使用 {1, 4, 3, 2},因为替换权重 {0, 0.3/3, 0.3/3, 0.3/3, 0.4} 具有总权重 = 0.6 的最后 3 个项目。
在实际示例中,子序列替换集很大。几乎任何短子序列都有替换。 很明显,这项任务可以使用蛮力来完成。但我正在寻找一种快速完成的方法。任何帮助,将不胜感激。
更新
实际上,我处理的是字符串而不是数字序列。到目前为止,我想出了以下算法(用 C# 实现):
public class Substitution
{
public string SubstituteWhat { get; private set; }
public string SubstituteTo { get; private set; }
public double TotalWeight { get; private set; }
public double SymbolWeight { get; private set; }
public Substitution(string substituteWhat, string substituteTo, double totalWeight)
{
SubstituteWhat = substituteWhat;
SubstituteTo = substituteTo;
TotalWeight = totalWeight;
SymbolWeight = TotalWeight/SubstituteWhat.Length;
}
public override string ToString()
{
return string.Format("SubstituteWhat: {0}, SubstituteTo: {1}, TotalWeight: {2}", SubstituteWhat, SubstituteTo, TotalWeight);
}
}
class SubstitutedStringWindowImpl
{
public string OriginalPhrase { get; set; }
public string SubstitutedPhrase { get; set; }
private double[] weightVector;
private double windowSum;
private int addItemPointer;
private int substructItemPoiner;
public SubstitutedStringWindowImpl(string phrase, int windowLength)
{
this.OriginalPhrase = phrase;
SubstitutedPhrase = String.Empty;
weightVector = new double[phrase.Length + windowLength ];
windowSum = 0;
substructItemPoiner = 0;
addItemPointer = windowLength;
}
public bool PerformSubstitution(
Substitution substitution,
double maxWeight,
out SubstitutedStringWindowImpl substitutedString)
{
substitutedString = MemberwiseClone() as SubstitutedStringWindowImpl;
substitutedString.weightVector = weightVector.ToArray();
for (int i = 0; i < substitution.SubstituteWhat.Length; i++)
{
substitutedString.weightVector[substitutedString.addItemPointer] = substitution.SymbolWeight;
substitutedString.windowSum = substitutedString.windowSum -
substitutedString.weightVector[substitutedString.substructItemPoiner] +
substitutedString.weightVector[substitutedString.addItemPointer];
substitutedString.substructItemPoiner++;
substitutedString.addItemPointer++;
if (substitutedString.windowSum > maxWeight)
return false;
if (substitutedString.addItemPointer == substitutedString.weightVector.Length)
break;
}
substitutedString.SubstitutedPhrase = SubstitutedPhrase + substitution.SubstituteTo;
return true;
}
}
internal class SubstitutionManagerWindowImpl
{
private readonly Dictionary<string, List<Substitution>> substitutionsDict;
private readonly double maxWeight;
private readonly int maxSubstitutionLength;
private readonly int windowLength;
public SubstitutionManagerWindowImpl(
List<Substitution> substitutions,
double maxWeight,
int windowLength)
{
this.substitutionsDict = substitutions.GroupBy(x => x.SubstituteWhat)
.ToDictionary(x => x.Key, x => x.ToList());
this.maxWeight = maxWeight;
this.windowLength = windowLength;
maxSubstitutionLength = substitutions.Max(x => x.SubstituteWhat.Length);
}
private List<SubstitutedStringWindowImpl> GetAllSubstitutionsPrivate(
SubstitutedStringWindowImpl stringToHandle, int symbolCount)
{
if (stringToHandle.OriginalPhrase.Length == symbolCount)
return new List<SubstitutedStringWindowImpl> {stringToHandle};
var result = new List<SubstitutedStringWindowImpl>();
for (int i = 1;
i <= Math.Min(maxSubstitutionLength, stringToHandle.OriginalPhrase.Length - symbolCount);
i++)
{
var subphraseToSubstitute = stringToHandle.OriginalPhrase.Substring(symbolCount, i);
List<Substitution> appropriateSubstitutions;
if (!substitutionsDict.TryGetValue(subphraseToSubstitute, out appropriateSubstitutions))
continue;
foreach (var substitution in appropriateSubstitutions)
{
SubstitutedStringWindowImpl handledString;
if (!stringToHandle.PerformSubstitution(substitution, maxWeight, out handledString))
continue;
result.AddRange(GetAllSubstitutionsPrivate(handledString,
symbolCount + substitution.SubstituteWhat.Length));
}
}
return result;
}
// this is the entry function
public List<string> GetAllSubstitutions(string phrase)
{
var res = GetAllSubstitutionsPrivate(new SubstitutedStringWindowImpl(phrase,windowLength), 0);
return res.Select(x => x.SubstitutedPhrase).ToList();
}
}
但它似乎无法快速完成工作。有什么改进的建议吗?
【问题讨论】:
-
您没有显示应该是有效替换的 12342。请解释一下好吗?
-
你找到什么方法了吗?答案中有哪些不同的选项?