- 不同的循环子字符串
给你一个字符串 text ,请你返回满足下述条件的 不同 非空子字符串的数目:
可以写成某个字符串与其自身相连接的形式(即,可以写为 a + a,其中 a 是某个字符串)。
例如,abcabc 就是 abc 和它自身连接形成的。
示例 1:
输入:text = “abcabcabc”
输出:3
解释:3 个子字符串分别为 “abcabc”,“bcabca” 和 “cabcab” 。
示例 2:
输入:text = “leetcodeleetcode”
输出:2
解释:2 个子字符串为 “ee” 和 “leetcodeleetcode” 。
提示:
1 <= text.length <= 2000
text 只包含小写英文字母。
题解
字符串不是很长,直接直接暴力枚举一遍长度为d时text[i:i+d-1]和text[i+d:i+2*d-1]相等的数目,那么问题变成了怎么优化判断这两个子串相等的时间,于是我们利用哈希映射,也就是Rabin-karp编码方式转换成数字,因为取模可能不同的字符串会取模后变成相同的数字,于是我们需要利用两个基地进行两次取模双重验证。
备注不能让字符’a’表示数字0,因为会导致’a’为0,'aa’也为0,这样是不对的,在数字上00和0是一样的,但是字符串而言不一样,区别对待,所以’a’表示数字1。
AC代码
class Solution {
public:
typedef long long ll;
ll mod1=10000000000000007;
ll mod2=1000000000000007;
struct Node
{
ll a,b;
};
vector<Node>q;
static int cmp(Node a1,Node a2)
{
if(a1.a<a2.a)return true;
if(a1.a==a2.a)return a1.b<a2.b;
return false;
}
int distinctEchoSubstrings(string text) {
int D=text.length()/2;
for(int d=1;d<=D;d++)
{
ll ans1_1=0,ans1_2=0;
ll ans2_1=0,ans2_2=0;
ll bas1=1,bas2=1;
for(int i=0;i<d;i++)
{
ans1_1*=26;
ans1_1+=(text[i]-'a'+1);
ans1_1%=mod1;
ans1_2*=26;
ans1_2+=(text[i]-'a'+1);
ans1_2%=mod2;
ans2_1*=26;
ans2_1+=(text[i+d]-'a'+1);
ans2_1%=mod1;
ans2_2*=26;
ans2_2+=(text[i+d]-'a'+1);
ans2_2%=mod2;
if(i>0)
{
bas1*=26;
bas2*=26;
bas1%=mod1;
bas2%=mod2;
}
}
if(ans1_1==ans2_1&&ans1_2==ans2_2)
{
Node t;
t.a=ans1_1,t.b=ans1_2;
q.push_back(t);
}
for(int i=1;i+2*d-1<text.length();i++)
{
ans1_1=(ans1_1+mod1-((text[i-1]-'a'+1)*bas1)%mod1)%mod1;
ans1_2=(ans1_2+mod2-((text[i-1]-'a'+1)*bas2)%mod2)%mod2;
ans2_1=(ans2_1+mod1-((text[i+d-1]-'a'+1)*bas1)%mod1)%mod1;
ans2_2=(ans2_2+mod2-((text[i+d-1]-'a'+1)*bas2)%mod2)%mod2;
ans1_1*=26;
ans1_1+=(text[i+d-1]-'a'+1);
ans1_1%=mod1;
ans1_2*=26;
ans1_2+=(text[i+d-1]-'a'+1);
ans1_2%=mod2;
ans2_1*=26;
ans2_1+=(text[i+2*d-1]-'a'+1);
ans2_1%=mod1;
ans2_2*=26;
ans2_2+=(text[i+2*d-1]-'a'+1);
ans2_2%=mod2;
if(ans1_1==ans2_1&&ans1_2==ans2_2)
{
Node t;
t.a=ans1_1,t.b=ans1_2;
q.push_back(t);
}
}
}
if(q.size()==0)return 0;//特判
sort(q.begin(),q.end(),cmp);
Node t=q[0];
int ans=1;
//cout<<t.a<<" "<<t.b<<endl;
for(int i=1;i<q.size();i++)
{
//cout<<t.a<<" "<<t.b<<endl;
if(t.a!=q[i].a||t.b!=q[i].b)
{
t=q[i];
ans++;
}
}
return ans;
}
};