我正在寻找一种能够在单个字符串中找到重复子串数的算法。
为此,我一直在寻找一些动态编程算法,但没有找到任何可以帮助我的算法。我只想要一些关于如何做到这一点的教程。
我们说我有一个字符串ABCDABCDABCD
。预期的输出为3
,因为有ABCD
次。{/ p>
对于输入AAAA
,输出为4
,因为A
重复了4次。
对于输入ASDF
,输出将为1
,因为每个字符仅重复一次。
我希望有人可以指出我正确的方向。谢谢。
答案 0 :(得分:3)
我采取以下假设:
ABCDABC
的情况下,ABC
不会被视为重复的子字符串,但在ABCABC
的情况下也是如此。ABCABC
的情况下,ABC
不会被视为重复的子字符串。AAAA
的情况下,答案应该是4
(a
是子字符串)而不是2
(aa
是子字符串)。 根据这些假设,算法如下:
inputString
。failure[]
。如果相对于弦的长度具有线性时间复杂度,则该操作。因此,根据定义,failure[i]
表示子串inputString[0....i]
的最长正确前缀的长度,该子串也是同一子串的正确后缀。len = inputString.length - failure.lastIndexValue
。此时,我们知道如果有任何重复字符串,那么它必须是这个长度len
。但我们需要检查一下;首先,只需检查len
是否完全划分inputString.length
(即inputString.length % len == 0
)。如果是,则检查len
个字符的每个连续(非重叠)子字符串是否相同;此操作再次具有相对于输入字符串长度的线性时间复杂度。inputString.length
/ len
。否则,答案只是inputString.length
,因为不存在这样的重复子字符串。总体时间复杂度为O(n)
,其中n
是输入字符串中的字符数。
计算KMP故障数组的示例代码为here。
例如,
让输入字符串为abcaabcaabca
。
它的KMP故障数组是 - [0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8]
。
所以,我们的len
=(12 - 8)= 4。
长度为4
的每个连续非重叠子字符串都相同(abca
)。
因此答案是12/4
= 3
。也就是说,abca
重复重复3次。
答案 1 :(得分:1)
使用C#的解决方案是:
class Program
{
public static string CountOfRepeatedSubstring(string str)
{
if (str.Length < 2)
{
return "-1";
}
StringBuilder substr = new StringBuilder();
// Length of the substring cannot be greater than half of the actual string
for (int i = 0; i < str.Length / 2; i++)
{
// We will iterate through half of the actual string and
// create a new string by appending the current character to the previous character
substr.Append(str[i]);
String clearedOfNewSubstrings = str.Replace(substr.ToString(), "");
// We will remove the newly created substring from the actual string and
// check if the length of the actual string, cleared of the newly created substring, is 0.
// If 0 it tells us that it is only made of its substring
if (clearedOfNewSubstrings.Length == 0)
{
// Next we will return the count of the newly created substring in the actual string.
var countOccurences = Regex.Matches(str, substr.ToString()).Count;
return countOccurences.ToString();
}
}
return "-1";
}
static void Main(string[] args)
{
// Input: {"abcdaabcdaabcda"}
// Output: 3
// Input: { "abcdaabcdaabcda" }
// Output: -1
// Input: {"barrybarrybarry"}
// Output: 3
var s = "asdf"; // Output will be -1
Console.WriteLine(CountOfRepeatedSubstring(s));
}
}
答案 2 :(得分:-1)
您想如何指定&#34;重复字符串&#34;?它是否只是第一组字符,直到a)再次找到第一个字符,b)模式开始重复,或c)其他一些标准?
所以,如果你的字符串是&#34; ABBAABBA&#34;,那是2,因为&#34; ABBA&#34;重复两次或是1,因为你有&#34; ABB&#34;其次是&#34; AAB&#34;?怎么样&#34; ABCDABCE&#34; - &#34; ABC&#34;计数(尽管&#34; D&#34;在重复之间?)在&#34; ABCDABCABCDABC&#34;中,是重复字符串&#34; ABCD&#34; (1)或&#34; ABCDABC&#34; (2)?
&#34; AAABBAAABB&#34; - 是3(&#34; AAA&#34;)还是2(&#34; AAABB&#34;)?
如果重复字符串的结尾是第一个字母的另一个实例,那很简单:
按字符逐个字符串工作,将每个字符放入另一个变量中,直到下一个字符与第一个字符匹配为止。然后,给定第二个变量中子字符串的长度,检查字符串的下一位以查看它是否匹配。继续,直到它不匹配或你到达字符串的末尾。
如果你只想找到任何长度模式重复,无论第一个字符是否在模式中重复,它就会变得更复杂(但幸运的是,这是计算机擅长的东西)。
你需要逐个字符地在另一个变量中构建一个模式,但是你还需要注意第一个字符重新出现并开始构建第二个子字符串,看它是否与第一个匹配。这可能应该放在一个数组中,因为您可能会遇到第一个字符的第三个(或更多)实例,这会触发需要跟踪另一个可能的匹配。
这并不难,但要记住很多,这是一个相当烦人的问题。你有没有特别的理由这样做?