📅  最后修改于: 2023-12-03 15:28:41.676000             🧑  作者: Mango
本题为GATE-CS-2003年的考题,主要考察算法和数据结构的知识。该题目要求程序员实现一个算法,判断一个字符串中是否存在一个长度大于等于2的子字符串,在该字符串中出现了至少两次。
实现函数 bool hasRepeatingSubstring(char str[])
,其参数 str
表示一个字符串。函数需要返回一个bool型的值,表示参数字符串中是否存在一个长度大于等于2的子字符串,在该字符串中出现了至少两次。
示例1:
输入:str = "ababc"
输出:true
解释:字符串"ab"在原字符串中出现了两次。
示例2:
输入:str = "abcd"
输出:false
解释:不存在长度大于等于2的子字符串,在该字符串中出现了至少两次。
本算法的主要思路是基于BK树的字符串相似度匹配算法,简单介绍如下:
BK树是一种二叉树,具体的构建和查询算法可以参考 BK树 - 算法导论笔记。
#include<bits/stdc++.h>
#include<iostream>
#include<unordered_map>
using namespace std;
struct node
{
string dat;
int dis;//哈希距离
node *s[2],*fa;
}*rt;
int n,N=131,P=233,f[1000003];
node *newnode(string x,node *fa=NULL)
{
node *p=new node;
p->dat=x;
p->dis=0;
p->s[0]=p->s[1]=NULL;
p->fa=fa;
return p;
}
void insert(string x)
{
//cout<<"req : "<<x<<endl;
if (rt==NULL)
{
rt=newnode(x);
return ;
}
node *p=rt;
while (p->s[(x[0]*N+x[1]*P)%1000003]!=NULL)
{
if (p->s[(x[0]*N+x[1]*P)%1000003]->dis==x.size()) return ;
else if (p->s[(x[0]*N+x[1]*P)%1000003]->dis==0)
{
break;
}
p=p->s[(x[0]*N+x[1]*P)%1000003];
}
if (p->dat==x||p->dis==x.size()) return ;
if (!p->dis) p->dis=x.size();
node *q=newnode(x,p);
p->s[(x[0]*N+x[1]*P)%1000003]=q;
//cout<<"x : "<<x<<endl;
}
void dfs(string x,node *p,vector<int> &ans)
{
if (p==NULL) return ;
if (x!=p->dat) ans.push_back(p->dis);
int l=x.size()-p->dis,r=p->dis;
//cout<<l<<' '<<r<<endl;
if (l<=0) dfs(x,p->s[0],ans);
if (r<=0) dfs(x,p->s[1],ans);
if (l<=5)//5为叶子打上的卡
{
if (p->s[0]==NULL) return ;
dfs(x,p->s[0],ans);
if (p->s[1]==NULL) return ;
dfs(x,p->s[1],ans);
}
if (r<=5)//5为叶子打上的卡
{
if (p->s[1]==NULL) return ;
dfs(x,p->s[1],ans);
if (p->s[0]==NULL) return ;
dfs(x,p->s[0],ans);
}
return ;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);
string x;
while (cin>>x)
{
insert(x);
f[x[0]*N+x[1]*P]++;
}
vector<int> ans;
for (x="a";x<="z";x[0]++/*减少循环次数*/)
{
for (string c="a";c<="z";c[0]++)
{
if (f[x[0]*N+c[0]*P]<2) continue;
ans.clear();
dfs(x,rt,ans);
if (ans.size()<2) continue;
int siz=ans.size();
sort(ans.begin(),ans.end());
for (int i=1;i<siz;++i)
{
if (ans[i]==ans[i-1])//二次判断
{
cout<<"true"<<endl;
return 0;
}
}
}
}
cout<<"false"<<endl;
}