由于从不同位置开始的相等子串算作不同的子串,所以长度为 n 的字符串的最大子串数为 n*(n + 1) / 2。(从位置 0 开始的 n 个子串,n-1 个子串从位置 1 开始,依此类推)。
如果一个丑陋的字符串包含在从位置 p 开始的长度为 q 的子串中,那么所有从 p 开始且长度 > q 的子串也将包含该丑陋的字符串。
如果丑陋的字符串比子字符串本身长,它将不匹配。
我的第一次尝试是这样的:
String ugly[]; // is provided somehow; at most 500000 with max length of 500000
String student; // the String to cut into substrings, max length 100000
long num = 0;
ugly.sort(); // by length
for (int start = 0; start < student.size() - 1, ++start) {
for (int end = start + 1; end < student.size(); ++end) {
String s = student.substr(start, end);
int lgth = s.size();
int u = 0;
while (lgth >= ugly[u].size()) {
if (s.contains(ugly[u])) break;
++u;
}
if (lgth < ugly[u].size()) {
++num; // we checked all potentially matching uglies
} else {
break; // leave the inner loop and
// start with the next position
}
}
}
我的第二次尝试将采用另一种方法。如果这个任务必须执行多次,我会开始开发这个。
如果我有一个字符串 student 和一个长度为 p 的丑陋字符串在某处匹配,则字符串 student 可以分为两部分:第一部分以丑陋字符串的前 p-1 个字符结尾第二部分以丑陋字符串的最后 p-1 个字符开头。
这可以重复,直到丑陋的字符串在任何地方都不匹配。然后我们有许多子字符串和一个不匹配的丑字符串。因此,这个丑陋的字符串可以被丢弃。
对所有丑陋的字符串重复此操作,您将获得与任何丑陋字符串都不匹配的“最长”子字符串列表。
现在您可以遍历此列表并将 length * (length + 1)/2 添加到最终结果中。
它看起来像
String ugly[]; // as before
String student; // as before
long num = 0;
Vector substrs = new Vector();
ugly.sort(); // by length
substrs.add(student);
void splitStr(String str2split, String pattern, Vector result)
{
if (str2split.size() < pattern.size()) {
result.add(str2split);
return;
} else {
int pos = str2split.contains(pattern); // returns position, -1 if not found
if (pos >= 0) { // found
String s1 = str2split.substr(0, pos + pattern.size() - 1);
String s2 = str2split.substr(pos + 1, str2split.size());
// add s1 and repeat split on s2
result.add(s1);
splitStr(s2, pattern, result);
} else {
// not found, entire string is ok
result.add(str2split);
}
}
}
for (int u = 0; u < ugly.size(); ++u) {
Vector newSubstrs = new Vector();
String ugly2test = ugly[u];
for (int i = 0; i < substrs.size(); ++i) {
String t = substrs.get(i);
splitStr(t, ugly2test, newSubstrs);
}
substrs = newSubstrs;
}
for (int i = 0; i < substrs.size(); ++i) {
String s = substrs.get(i);
num += s.size() * (s.size() + 1) / 2;
}
注意:这基本上是这个想法。我没有测试任何代码(类似于 java,但可能不会编译),我只是将我的纯文本想法翻译成某种伪代码。