我正在创建一个字体映射程序,我想要映射两种不同语言的字体。
例如,Arial字体(英文)中的A
将在Kruti Dev Font(印地语)中使用अ
进行映射。
我在数据库中以这种方式创建了这种转换:
Native_Font | Foreign_Language_Font
-------------------------------------------
A | अ
B | बी
如果转换仅限于字符,则可以。读取本机字体的每个字符,并在外语字体中查找其匹配的字符。 (我已经完成了)
但现在我必须为字符串做这件事,这就是真正的问题开始的地方。
如果在数据库中提供了字符串,则将其完全转换。但是如果它的转换不存在,那么找到一个字符的转换就少了。
一个例子是
在数据库中
Native_Font | Foreign_Language_Font
-------------------------------------------
Cha | चा
r | र
t | ट
和单词Chart
用于翻译。
Chart
。如果找到它的映射立即给出。 Chart
的直接转换,请转到Char
。如果立即找到其映射,则找到t
等等
Chart
Char t
Cha rt
Cha r t
Ch art
Ch ar t
Ch a r t
C hart
C har t
C ha r t
C h a r t
此外,如果未找到映射,则应将其替换为本机字体字符。怎么做?我确信应该使用递归。但是怎么样?
答案 0 :(得分:1)
我会用一种贪婪的算法来接近它。像这样:
// warning, untested
public String Translate(String s, Dictionary<String, String> mapping)
{
String result = "";
if (RecurTranslate(s, mapping, ref result))
return result;
throw new Exception("No translation");
}
private bool RecurTranslate(String s, Dictionary<String, String> mapping, ref String result)
{
if (s.Length == 0)
return true;
for (int prefixLen = s.Length; prefixLen > 0; --prefixLen)
{
String prefix = s.Substring(0, prefixLen);
String trans;
if (mapping.TryGetValue(prefix, out trans))
{
if (RecurTranslate(s.Substring(prefixLen), mapping, ref result))
{
result = trans + result;
return true;
}
}
else if (prefixLen == 1)
{ // this branch allows a character to stand for itself
if (RecurTranslate(s.Substring(prefixLen), mapping, ref result))
{
result = prefix + result;
return true;
}
}
}
return false;
}
这从前面开始,寻找最大可能的匹配。根据您的数据,其他方法可能会更好 - 例如,按照长度顺序浏览映射以找到最长匹配并从那里拆分:
private bool RecurTranslate2(String s, Dictionary<String, String> mapping, ref String result)
{
if (s.Length == 0)
return true;
foreach (var entry in mapping.Where(e => e.Key.Length <= s.Length).OrderByDescending(e => e.Key.Length))
{
if (s.Contains(entry.Key))
{ // split into a before and after
int idx = s.IndexOf(entry.Key);
String before = s.Substring(0, idx);
String after = s.Substring(idx + entry.Key.Length);
String bRes = "", aRes = "";
if (RecurTranslate2(before, mapping, ref bRes) && RecurTranslate2(after, mapping, ref aRes))
{
result = aRes + entry.Value + bRes;
return true;
}
}
}
return false;
}
最后,您可以使用组合这些方法:使用RecurTranslate2,直到达到某个长度阈值,然后切换到RecurTranslate。
回应评论:请参阅新的其他分支以查找失败
答案 1 :(得分:0)
递归版本 - O(2 ^(string.Length-1)) - 不要在更大的字符串上运行
[Test]
public void StringSplit()
{
var splits = AllPossibleSplits("hello".Select(c => c.ToString()).ToList());
Assert.AreEqual(16, splits.Count);
Assert.AreEqual("hello", splits.First().First());
Assert.AreEqual("hello".Length, splits.Last().Count());
}
private List<List<string>> AllPossibleSplits(List<string> source)
{
if (source.Count == 0)
{
return new List<List<string>>();
}
if (source.Count == 1)
{
return new List<List<string>> { source };
}
var firstTwoJoined = new List<string> { source[0] + source[1] };
firstTwoJoined.AddRange(source.Skip(2));
var justFirst = new List<string> { source[0] };
var withoutFirst = AllPossibleSplits(source.Skip(1).ToList());
var result = new List<List<string>>();
result.AddRange(AllPossibleSplits(firstTwoJoined));
result.AddRange(withoutFirst.Select(list => justFirst.Concat(list).ToList()));
return result;
}
答案 2 :(得分:0)