zoukankan      html  css  js  c++  java
  • 1044. 最长重复子串

    1044. 最长重复子串 - 力扣(LeetCode) (leetcode-cn.com)

    暴力失败 滑动窗口失败

      1 class Solution {
      2 public:
      3     // 暴力
      4     // string longestDupSubstring(string s) {
      5     //     string ans;
      6     //     vector<string> anss;
      7     //     for(int i = 0; i<s.size(); i++){
      8     //         for(int j = i+1; j<s.size(); j++){
      9     //             string tmp = s.substr(i, j-i);
     10     //             if(s.find(tmp)!=s.rfind(tmp) && s.rfind(tmp)!=-1){
     11     //                 anss.push_back(tmp);
     12     //                 cout<<tmp<<endl;
     13     //             }
     14     //         }
     15     //     }
     16     //     sort(anss.begin(), anss.end(), [](string a, string b)->bool{return a.size()>b.size();});
     17     //     return anss.size() == 0?"":anss[0];
     18     // }
     19 
     20     // 小优化
     21     // string longestDupSubstring(string s) {
     22     //     string ans;
     23     //     vector<string> anss;
     24     //     int bigger_size = 0;
     25     //     for(int i = 0; i<s.size(); i++){
     26     //         for(int j = i+1; j<s.size(); j++){
     27     //             string tmp = s.substr(i, j-i);
     28     //             if(s.find(tmp)!=s.rfind(tmp) && s.rfind(tmp)!=-1){
     29     //                 anss.push_back(tmp);
     30     //                 bigger_size = bigger_size>tmp.size()?bigger_size:tmp.size();
     31     //             }else break;
     32     //         }
     33     //     }
     34     //     sort(anss.begin(), anss.end(), [](string a, string b)->bool{return a.size()>b.size();});
     35     //     return anss.size() == 0?"":anss[0];
     36     // }
     37 
     38     // 滑动窗口 仍然超时
     39     // string longestDupSubstring(string s) {
     40     //     string ans;
     41     //     int bigger_size = 0;
     42     //     int i = 0, j = 1;
     43     //     while(i<s.size() && j<s.size()){
     44     //         string tmp = s.substr(i, j-i);  
     45     //         if(s.find(tmp)!=s.rfind(tmp) && s.rfind(tmp)!=-1 && tmp.size()>bigger_size){
     46     //             bigger_size = tmp.size();
     47     //             ans = tmp;
     48     //         }
     49     //         else
     50     //             i++;
     51     //         j++;  
     52     //     }
     53     //     return ans;
     54     // }
     55
     1     // 滑动窗口 优化 单个不超时 提交超时
     2     // string longestDupSubstring(string s) {
     3     //     string ans;
     4     //     int bigger_size = 0;
     5     //     int i = 0, j = 1;
     6     //     while(i<s.size() && j<s.size()){
     7     //         string tmp = s.substr(i, j-i);
     8     //         if(s.find(tmp)!=s.rfind(tmp) && s.rfind(tmp)!=-1 && tmp.size()>bigger_size){
     9     //             bigger_size = tmp.size();
    10     //             j = i+bigger_size;
    11     //             ans = tmp;
    12     //         }
    13     //         else
    14     //             i++;
    15     //         j++;
    16     //     }
    17     //     return ans;
    18     // }
     56     // 从大到小
     57     // string longestDupSubstring(string s) {
     58     //     string ans;
     59     //     int findsize = s.size()-1;
     60     //     bool find = 0;
     61     //     while(findsize>0){
     62     //         for(int i = 0; i<s.size(); i++){
     63     //             if(i+findsize>s.size()-1) break;
     64     //             string tmp = s.substr(i, findsize);
     65     //             cout<< tmp<<endl;
     66     //             if(s.find(tmp)!=s.rfind(tmp) && s.rfind(tmp)!=-1){
     67     //                 ans = tmp;
     68     //                 find = 1;
     69     //                 break;
     70     //             }
     71     //         }
     72     //         if(find == 1) break;
     73     //         findsize--;
     74     //     }
     75     //     return ans;
     76     // }
     77 
     78     typedef pair<long long, long long> pll;
     79     long long pow(int a, int m, int mod) {
     80         long long ans = 1;
     81         long long contribute = a;
     82         while (m > 0) {
     83             if (m % 2 == 1) {
     84                 ans = ans * contribute % mod;
     85                 if (ans < 0) {
     86                     ans += mod;
     87                 }
     88             }
     89             contribute = contribute * contribute % mod;
     90             if (contribute < 0) {
     91                 contribute += mod;
     92             }
     93             m /= 2;
     94         }
     95         return ans;
     96     }
     97 
     98     int check(const vector<int> & arr, int m, int a1, int a2, int mod1, int mod2) {
     99         int n = arr.size();
    100         long long aL1 = pow(a1, m, mod1);
    101         long long aL2 = pow(a2, m, mod2);
    102         long long h1 = 0, h2 = 0;
    103         for (int i = 0; i < m; ++i) {
    104             h1 = (h1 * a1 % mod1 + arr[i]) % mod1;
    105             h2 = (h2 * a2 % mod2 + arr[i]) % mod2;
    106             if (h1 < 0) {
    107                 h1 += mod1;
    108             }
    109             if (h2 < 0) {
    110                 h2 += mod2;
    111             }
    112         }
    113         // 存储一个编码组合是否出现过
    114         set<pll> seen;
    115         seen.emplace(h1, h2);
    116         for (int start = 1; start <= n - m; ++start) {
    117             h1 = (h1 * a1 % mod1 - arr[start - 1] * aL1 % mod1 + arr[start + m - 1]) % mod1;
    118             h2 = (h2 * a2 % mod2 - arr[start - 1] * aL2 % mod2 + arr[start + m - 1]) % mod2;
    119             if (h1 < 0) {
    120                 h1 += mod1;
    121             }
    122             if (h2 < 0) {
    123                 h2 += mod2;
    124             }
    125 
    126             // 如果重复,则返回重复串的起点
    127             if (seen.count(make_pair(h1, h2))) {
    128                 return start;
    129             }
    130             seen.emplace(h1, h2);
    131         }
    132         // 没有重复,则返回-1
    133         return -1;
    134     }
    135 
    136     string longestDupSubstring(string s) {
    137         srand((unsigned)time(NULL));
    138         // 生成两个进制
    139         int a1 = random()%75 + 26;
    140         int a2 = random()%75 + 26;
    141 
    142         // 生成两个模
    143         int mod1 = random()%(INT_MAX - 1000000006) + 1000000006;
    144         int mod2 = random()%(INT_MAX - 1000000006) + 1000000006;
    145         int n = s.size();
    146         // 先对所有字符进行编码
    147         vector<int> arr(n);
    148         for (int i = 0; i < n; ++i) {
    149             arr[i] = s[i] - 'a';
    150         }
    151         // 二分查找的范围是[1, n-1]
    152         int l = 1, r = n - 1;
    153         int length = 0, start = -1;
    154         while (l <= r) {
    155             int m = l + (r - l + 1) / 2;
    156             int idx = check(arr, m, a1, a2, mod1, mod2);
    157             if (idx != -1) {
    158                 // 有重复子串,移动左边界
    159                 l = m + 1;
    160                 length = m;
    161                 start = idx;
    162             } else {
    163                 // 无重复子串,移动右边界
    164                 r = m - 1;
    165             }
    166         }
    167         return start != -1 ? s.substr(start, length) : "";
    168     }
    169 };
  • 相关阅读:
    BZOJ 5297: [Cqoi2018]社交网络 矩阵树定理
    BZOJ 5300: [Cqoi2018]九连环 打表+FFT
    BZOJ 5298: [Cqoi2018]交错序列 二项式定理+矩阵乘法
    BZOJ 5301: [Cqoi2018]异或序列 莫队+桶
    BZOJ 5324: [Jxoi2018]守卫 区间DP
    BZOJ 5322: [Jxoi2018]排序问题 模拟+贪心
    点斜式
    斜截式
    斜率
    求线段的交点
  • 原文地址:https://www.cnblogs.com/qianxunslimg/p/15725752.html
Copyright © 2011-2022 走看看