题目解析:求回声字符串的个数,也就是求头半段等于后半段的字符串的个数。
解法一:遍历长度为l的每一子字符串,时间复杂度为O(n^2) , 判断子字符串的的前半段是否等于后半段,总的时间复杂度为O(N^3).会超时;
class Solution {
public:
int distinctEchoSubstrings(string text)
{
int len = text.size() ;
//vector<vector<int>> dp(len , vector<int>(len , 0)) ;
//int modl = 1e18 + 7 ;
unordered_set<string> res ;
for(int split = 1 ; split < len ; split++)
for(int l = 1 ; split - l >= 0 && split + l <= len ; l++)
if(text.compare(split - l , l , text , split , l) == 0) res.insert(text.substr(split , l)) ;
return res.size() ;
}
};
解法二:优化:使用kmp算法,求每一子字符串的kmp长度是否大于等于子字符串长度的一半,若等于一半就一定满足条件;但是还得进一步考虑如果大于一半的情况,如果(l/2%(l - kmpl) == 0),则满足条件。时间复杂度近似为O(N^2logN) , 空间复杂度为O(N^2);可进一步将空间复杂度优化为O(N) ;
class Solution {
public:
int distinctEchoSubstrings(string text)
{
int len = text.size() ;
vector<vector<int>> dp(len , vector<int>(len , 0)) ;
unordered_set<string> res ;
for(int i = 0 ; i < len ; i++)
{
for(int j = i + 1 ; j < len ; j++)
{
int k = dp[i][j-1] ;
while(k != 0 && text[i+k] != text[j] ) k = dp[i][i + k - 1] ;
if(text[i+k] == text[j]) k++ ;
dp[i][j] = k ;
if((j - i + 1) % 2 == 0 && k * 2 >= j - i + 1 && (j - i + 1) / 2 % (j - i + 1 - k) == 0) res.insert(text.substr(i , j - i + 1)) ;
}
}
return res.size() ;
}
};
解法三:使用滚动hash的方法,计算字符串的hash值,那么就可以在O(1)时间比较两字符串是否相等 , 但是因为l长度最多为2000,可能会存在hash冲突。但是因为比较的两个字符串长度一样,所以不必担心hash冲突。时间复杂度降为O(N^2);
class Solution {
public:
int distinctEchoSubstrings(string text)
{
int len = text.size() ;
//vector<vector<int>> dp(len , vector<int>(len , 0)) ;
int modl = 1e9 + 7 ;
unordered_set<string> res ;
for(int split = 1 ; split < len ; split++)
{
long long hashl = 0 , hashr = 0 , base = 1 ;
for(int l = 1 ; split - l >= 0 && split + l <= len ; l++)
{
hashl = (hashl + base * (text[split - l] - ‘a‘)) % modl ;
hashr = (hashr * 26 + text[split + l - 1] - ‘a‘) % modl;
base = (base * 26) % modl;
if(hashl == hashr) res.insert(text.substr(split , l)) ;
}
}
return res.size() ;
}
};
解法四:为了避免回声字符串重复,将所有字符串插入到unordered_set<string>中,但是字符串插入到hashset中还需要hash一次,重复计算了字符串的hash值,所以可以直接插入字符串的hash值;
class Solution {
public:
int distinctEchoSubstrings(string text)
{
int len = text.size() ;
//vector<vector<int>> dp(len , vector<int>(len , 0)) ;
long long modl = 1e15 + 7 ;
unordered_set<int> res ;
for(int split = 1 ; split < len ; split++)
{
long long hashl = 0 , hashr = 0 , base = 1 ;
for(int l = 1 ; split - l >= 0 && split + l <= len ; l++)
{
hashl = (hashl + base * (text[split - l])) % modl ;
hashr = (hashr * 26 + text[split + l - 1]) % modl;
base = (base * 26) % modl;
//cout<<text.substr(split - l , l)<<" "<<hashl<<" "<<text.substr(split , l)<<" "<<hashr<<endl;
if(hashl == hashr) res.insert(hashl) ;
}
}
return res.size() ;
}
};
原文:https://www.cnblogs.com/mychen06/p/12590836.html