Xin chào mọi người, đây là đề bài:
Còn đây là hướng dẫn:
Em đã dùng rolling hash để tính binary search tìm max length. Nó chạy đúng kết quả nhưng lại bị time limit exceed. Tuy dùng Binary search và rolling hash đã giảm đáng kể thời gian. nhưng mà em thấy rất khó để được time complexity O(|s|+|t|). Đó là chưa kể em mới tính có 1 cái hash thôi là đã nhức đầu rồi :)). Có phải em đã tiếp cận sai hướng hay không. Mong các anh đọc và gợi ý giúp em, em xin cảm ơn nhiều.
// Assignment3Problem5.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
long long prime1 = 1000000007, prime2 = 1000000009;
using namespace std;
struct Answer {
size_t i, j, len;
};
vector<long long> powFunc(string s, int x, long long prime)
{
vector<long long> result(s.length() + 1);
result[0] = 1;
for (int i = 1; i <= s.length(); i++)
{
result[i] = ((result[i - 1] % prime)*(x%prime) + prime) % prime;
}
return result;
}
vector<long long> hashValues(string s, long long prime, int x)
{
vector<long long> result(s.length() + 1);
result[0] = 0;
for (int i = 1; i <= s.length(); i++)
{
result[i] = (x * result[i - 1] + s[i - 1]) % prime;
}
return result;
}
bool isSubstring(string s, string t, int length, vector<long long> table1, vector<long long> table2, vector<long long> powTable1, vector<long long> powTable2)
{
for (int i = length; i <= s.length(); i++)
{
long long hash1 = ((table1[i] - (powTable1[length] * table1[i - length])) % prime1 + prime1) % prime1;
for (int j = length; j <= t.length(); j++)
{
long long hash2 = ((table2[j] - (powTable2[length] * table2[j - length])) % prime1 + prime1)%prime1;
if (hash1 == hash2) return true;
}
}
return false;
}
int binarySearch(string s, string t, int left, int right, vector<long long> table1, vector<long long> table2, vector<long long> powerFun1, vector<long long> powerFun2)
{
if (left > right) return left - 1;
int mid = (left + right) / 2;
if (isSubstring(s, t, mid, table1, table2, powerFun1, powerFun2) == true)
return binarySearch(s, t, mid + 1, right, table1, table2, powerFun1, powerFun2);
return binarySearch(s, t, left, mid - 1, table1, table2, powerFun1, powerFun2);
}
Answer solve(const string &s, const string &t) {
Answer ans = { 0, 0, 0 };
/*
for (size_t i = 0; i < s.size(); i++)
for (size_t j = 0; j < t.size(); j++)
for (size_t len = 0; i + len <= s.size() && j + len <= t.size(); len++)
if (len > ans.len && s.substr(i, len) == t.substr(j, len))
ans = { i, j, len };
*/
int x = 3;
vector<long long> hashTable1 = hashValues(s, prime1, x);
vector<long long> hashTable2 = hashValues(t, prime1, x);
vector<long long> powTable1 = powFunc(s, x, prime1);
vector<long long> powTable2 = powFunc(t, x, prime1);
int maxLength = binarySearch(s, t, 0, min(s.length(), t.length()), hashTable1, hashTable2, powTable1, powTable2);
for (int i = maxLength; i <= s.length(); i++)
{
long long hash1 = ((hashTable1[i] - powTable1[maxLength] * hashTable1[i - maxLength]) % prime1 + prime1) % prime1;
for (int j = maxLength; j <= t.length(); j++)
{
long long hash2 = ((hashTable2[j] - powTable2[maxLength] * hashTable2[j - maxLength]) % prime1 + prime1) % prime1;
if (hash1 == hash2)
{
ans.i = i - maxLength;
ans.j = j - maxLength;
ans.len = maxLength;
return ans;
}
}
}
ans.i = 0;
ans.j = 0;
ans.len = 0;
return ans;
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
string s, t;
while (cin >> s >> t) {
auto ans = solve(s, t);
cout << ans.i << " " << ans.j << " " << ans.len << "\n";
}
}