我需要开发一种有效的算法来确定给定具有重复内容(并且仅重复内容)的字符串的唯一(重复)字符串...
例如:
"AbcdAbcdAbcdAbcd"
=>"Abcd"
"Hello"
=>"Hello"
我在想出一个相当有效的算法时遇到了一些麻烦;任何意见将不胜感激。
澄清:我想要最短的字符串,当重复足够多次时,等于总字符串。
我需要开发一种有效的算法来确定给定具有重复内容(并且仅重复内容)的字符串的唯一(重复)字符串...
例如:
"AbcdAbcdAbcdAbcd"
=>"Abcd"
"Hello"
=>"Hello"
我在想出一个相当有效的算法时遇到了一些麻烦;任何意见将不胜感激。
澄清:我想要最短的字符串,当重复足够多次时,等于总字符串。
private static string FindShortestRepeatingString(string value)
{
if (value == null) throw new ArgumentNullException("value", "The value paramter is null.");
for (int substringLength = 1; substringLength <= value.Length / 2; substringLength++)
if (IsRepeatingStringOfLength(value, substringLength))
return value.Substring(0, substringLength);
return value;
}
private static bool IsRepeatingStringOfLength(string value, int substringLength)
{
if (value.Length % substringLength != 0)
return false;
int instanceCount = value.Length / substringLength;
for (int characterCounter = 0; characterCounter < substringLength; characterCounter++)
{
char currentChar = value[characterCounter];
for (int instanceCounter = 1; instanceCounter < instanceCount; instanceCounter++)
if (value[instanceCounter * substringLength + characterCounter] != currentChar)
return false;
}
return true;
}
像这样的东西:
public string ShortestRepeating(string str)
{
for(int len = 1; len <= str.Length/2; len++)
{
if (str.Length % len == 0)
{
sub = str.SubString(0, len);
StringBuilder builder = new StringBuilder(str.Length)
while(builder.Length < str.Length)
builder.Append(sub);
if(str == builder.ToString())
return sub;
}
}
return str;
}
这只是从头开始查看子字符串,然后重复它们以查看它们是否匹配。它还会跳过任何长度不均匀地划分为原始字符串长度并且仅上升到 length / 2 的任何内容,因为超过该长度的任何内容都不能成为重复的候选对象。
也许这可以工作:
static string FindShortestSubstringPeriod(string input)
{
if (string.IsNullOrEmpty(input))
return input;
for (int length = 1; length <= input.Length / 2; ++length)
{
int remainder;
int repetitions = Math.DivRem(input.Length, length, out remainder);
if (remainder != 0)
continue;
string candidate = input.Remove(length);
if (String.Concat(Enumerable.Repeat(candidate, repetitions)) == input)
return candidate;
}
return input;
}
我会用这样的东西:
private static string FindRepeat(string str)
{
var lengths = Enumerable.Range(1, str.Length - 1)
.Where(len => str.Length % len == 0);
foreach (int len in lengths)
{
bool matched = true;
for (int index = 0; matched && index < str.Length; index += len)
{
for (int i = index; i < index + len; ++i)
{
if (str[i - index] != str[i])
{
matched = false;
break;
}
}
}
if (matched)
return str.Substring(0, len);
}
return str;
}
试试这个正则表达式:
^(\w*?)\1*$
它捕获尽可能少的字符,其中捕获的序列(并且仅捕获的序列)重复 0 次或更多次。根据 Jacob 的回答,您可以在之后的捕获中获取最短匹配的文本。
您可以使用带有反向引用的正则表达式。
Match match = Regex.Match(@"^(.*?)\0*$");
String smallestRepeat = match.Groups[0];