zoukankan      html  css  js  c++  java
  • 最长重复子串(leetcode)

    题目链接:https://leetcode-cn.com/problems/longest-duplicate-substring/

     题号:1044

    题目描述:

    给出一个字符串 S,考虑其所有重复子串(S 的连续子串,出现两次或多次,可能会有重叠)。
    
    返回任何具有最长可能长度的重复子串。(如果 S 不含重复子串,那么答案为 ""。)。

    示例1:

    输入:"banana"
    输出:"ana"

    示例2:

    输入:"abcd"
    输出:""

    题目分析:

    leetcode上大佬说的:

    我用具体的例子解释一下: “因此我们可以使用二分查找的方法,找到最大的 L “
    
    这个"因此"不太显然我觉得。首先明确,二分查找的目的是:选取子串长度L,然后交给Rabin-Karp计算是否存在长度有L的重复子串,如果存在,则尝试长度更长的子串。
    
    我懒得写题解,就用序号啦,将就看吧各位。
    
    以题解中子任务一的示意图为例,当前串为“leetcodecookies”,长度为15,用两个指针left=1,right=15指向首尾。
    (这里先提一下,left不仅仅是一个指针,二分结束时还可以通过Left得知最终的找到的最大长度l,这个地方没懂不要紧,看了下面再回过来看也行。) 通过(left
    +right)/2计算mid值为8,则通过Rarbin-Karp(代码中对应(search()函数)计算是否有长度为8的重复子串。

    显然没有,即search函数返回-1,说明8比最长重复子串的长度长。所以需要缩小这个长度,我们让right=mid=8
    再重新计算mid,看到这里应该能感觉出来,mid值其实就是二分查找不断测试的长度值,就是“选取”。 再计算之后mid
    =(1+8)/2=4,再交给search计算,search返回值仍然是-1,所以再让right=mid,再计算mid=2,此时交给seach函数返回值不为1。
    说明存在长度为2的重复子串,此时应该移动left,来使得选取的mid值增大,以查看比2长的重复字串是否存在。 令left
    =mid+1=3,再计算mid=(3+4)=3,再交给search,返回值为-1,不存在长度为3的重复子串,让right=mid=3,此时left=right,while终止。 所以最长重复子串长度为2,怎么计算这个长度呢?答案是left - 1。因为left的值一定是上一个成功检测到重复的mid值+1

    代码:

    c++:

    leetcode:(超时)

    PTA:

    #pragma warning(disable:4996)
    #include <iostream>
    #include <string>
    #include <unordered_map>
    using namespace std;
    string a;
    string ans = "";
    int search(int r, int l)
    {
        string b;
        unordered_map<string, int>hs;
        int len = r - 1, flag;
        while (l + len <= a.length())
        {
            b = a.substr(l, len);
            if (!hs[b])
            {
                hs[b] = l;
                l++;
            }
            else
            {
                len++;
                while (l + len < a.length() && a[hs[b] + len] == a[l + len])
                {
                    len++;
                }
                flag = len - 1;
                b = a.substr(l, len - 1);
                ans = b;
                if (l + len < a.length())
                {
                    string c = a.substr(hs[b], len);
                    string d = a.substr(l, len);
                    hs[c] = hs[b];
                    hs[d] = l;
                    l++;//继续遍历,找出是否还有长度大于len的子串
                }
                else
                    return flag;
            }
        }
        if (ans.empty())
            return 0;
        else
            return flag;
    }
    int main()
    {
        getline(cin, a);
        a.insert(0, "!");
        int r = a.length() - 1;
        int l = 1;
        int flag = 1;
        while (l != r)
        {
            int mid = l + (r - l + 1) / 2;
            if ((flag = search(mid, flag)) && flag != 0)
                break;
            else
                r = mid - 1;
        }
        cout << flag << " " << ans;
    }
    /*
    qwertyuqwertdfqwerty
    */
  • 相关阅读:
    重写Override和重加载Overload
    Java 继承
    poj 3263 Tallest Cow
    矩阵求和
    全排列
    最大乘积
    三角形面积
    Sum
    搭积木
    调手表
  • 原文地址:https://www.cnblogs.com/zjw1324399/p/14319540.html
Copyright © 2011-2022 走看看