📜  门| GATE-CS-2003 |第 76 题(1)

📅  最后修改于: 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树的字符串相似度匹配算法,简单介绍如下:

  1. 将字符串 $str$ 切分为所有长度$\ge 2$的子串。
  2. 对所有子串计算出哈希值。
  3. 根据哈希值构建BK树。
  4. 遍历所有子串,判断其是否在BK树中至少重复了2次。

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;
}