//由于每次都是固定,长度所以不用h和p的数组 classSolution { public: using ull = unsignedlonglong;//超出后自动取模 const ull b = 131; string longestDupSubstring(string s){ int l = 0, n = s.length(), r = n - 1, pos = 0; auto check = [&](int k) { //返回的是以i为起始位置长度为k的字串 ull h = 0, p = 1; for (int i = 0; i < k; ++i) { h = h * b + s[i]; p = p * b; } unordered_set<ull> st{h}; for (int i = k; i < n; ++i) { h = h * b + s[i] - p * s[i - k]; //由于h就是长度为k+1的前缀和,只需-p[i-k] if (st.count(h)) return i; st.insert(h); } return0; //没有找到就返回0 }; while (l < r) { int m = (l + r + 1) >> 1; int ret; (ret = check(m)) ? l = m : r = m - 1; ret ? pos = ret : pos; } // 最终 l = r;为长度 cout << l << r <<endl; return s.substr(pos - l + 1, l); } };
//h和p都用数组存 classSolution { public: using ull = unsignedlonglong;//超出后自动取模 const ull b = 131; //前缀数组包含当前i值 ull h[30005]; ull p[30005]; string longestDupSubstring(string s){ int l = 0, n = s.length(), r = n - 1, pos = 0; h[0] = s[0],p[0] = 1; for (int i = 1; i < n; ++i) { h[i] = h[i-1] * b + s[i]; p[i] = p[i-1] * b; } auto check = [&](int k) { //返回的是以i为起始位置长度为k的字串 unordered_set<ull> st{}; for (int i = 0; i + k - 1 < n ; ++i) {//枚举起始点 int j = i + k - 1; ull temp ; if (i == 0) temp = h[j]; else temp = h[j] - h[i-1] * p[j - i + 1]; //cur = h[right] - h[left-1] *(p[right - left + 1] 或者 p [len]) if (st.count(temp)) return i;//返回数组的结尾的位置(根据return值定义) st.insert(temp); } return0; //没有找到就返回0 }; while (l < r) { int m = (l + r + 1) >> 1; int ret; (ret = check(m)) ? l = m : r = m - 1; ret ? pos = ret : pos; } // 最终 l = r;为长度 cout << l << r <<endl; return s.substr(pos, l); } };