查找字符串所有后缀的最长前缀字符串的长度。
例如字符串ababaa
的后缀为ababaa
,babaa
,abaa
,baa
,aa
和a
。每个字符串与字符串“ababaa”的相似性分别为6,0,3,0,1,1。因此答案是6 + 0 + 3 + 0 + 1 + 1 = 11.
我写了以下代码
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <time.h>
int main ( int argc, char **argv) {
size_t T;
std::cin >> T;
char input[100000];
for ( register size_t i = 0; i < T; ++i) {
std::cin >> input;
double t = clock();
size_t len = strlen(input);
char *left = input;
char *right = input + len - 1;
long long sol = 0;
int end_count = 1;
while ( left < right ) {
if ( *right != '\0') {
if ( *left++ == *right++ ) {
sol++;
continue;
}
}
end_count++;
left = input; // reset the left pointer
right = input + len - end_count; // set right to one left.
}
std::cout << sol + len << std::endl;
printf("time= %.3fs\n", (clock() - t) / (double)(CLOCKS_PER_SEC));
}
}
工作正常,但是对于100000
长并且具有相同字符即aaaaaaaaaa.......a
的字符串,需要很长时间,我该如何优化这一字符。
答案 0 :(得分:3)
答案 1 :(得分:1)
假设你的ababaa
是模式P.
我想你可以使用以下算法:
答案 2 :(得分:1)
使用Z
算法来计算所有子串的长度,这些子串的长度也以O(n)
为前缀,然后扫描结果数组并将其值求和。
参考:https://www.geeksforgeeks.org/sum-of-similarities-of-string-with-all-of-its-suffixes/
答案 3 :(得分:0)
从我所看到的,你使用普通数组来评估后缀,虽然它可能对某些数据集有效,但对于某些情况,例如你提到的那种情况,它将无效。
您需要实现前缀树或Trie之类的数据结构。这些代码并不简单,所以如果你不熟悉它们,我建议你仔细阅读它们。
答案 4 :(得分:0)
我不确定Trie是否会给你带来很大的性能提升......但我肯定会考虑它。
我的另一个想法是尝试压缩你的字符串。我没想过,只是一个疯狂的想法...
如果您有这样的字符串:ababaa
将其压缩为:abab2a
。然后你必须提出一种技术,你可以使用你的算法与这些字符串。优点是您可以有效地将长字符串100000a
相互比较。或者更重要的是:你可以非常快地计算你的总和。
但同样,我没有想到,也许这是一个非常糟糕的主意;)
答案 5 :(得分:0)
这是一个java实现:
// sprefix
String s = "abababa";
Vector<Integer>[] v = new Vector[s.length()];
int sPrefix = s.length();
v[0] = new Vector<Integer>();
v[0].add(new Integer(0));
for(int j = 1; j < s.length(); j++)
{
v[j] = new Vector<Integer>();
v[j].add(new Integer(0));
for(int k = 0; k < v[j - 1].size(); k++)
if(s.charAt(j) == s.charAt(v[j - 1].get(k)))
{
v[j].add(v[j - 1].get(k) + 1);
v[j - 1].set(k, 0);
}
}
for(int j = 0; j < v.length; j++)
for(int k = 0; k < v[j].size(); k++)
sPrefix += v[j].get(k);
System.out.println("Result = " + sPrefix);