acm.timus.ru からこの問題を解決しようとしていましたが、これは基本的に、特定の文字列 (最大長 5000) の異なる部分文字列の数を出力することを望んでいます。
私が提示しようとしている解決策は、非常に非効率的であり、制約を考えると制限時間超過の評決を受ける運命にあります。ただし、これら2つのソリューションが異なる唯一の方法は(少なくとも私が見る/理解できる限り)、一方がを使用std::map<long long, bool>
し、他方が使用するstd::set <long long>
ことです(最後のforループの開始を参照してください。残りは同一です。確認できます任意の差分ツールによる)。マップ ソリューションの結果は「テスト 3 で制限時間超過」になりますが、セット ソリューションの結果は「テスト 2 で制限時間超過」になります。これは、テスト 2 では、マップ ソリューションがセット ソリューションよりも速く機能することを意味します。これは、Microsoft Visual Studio 2010 コンパイラを選択した場合です。GCC を選択すると、どちらのソリューションもテスト 3 で TLE になります。
問題を効率的に解決する方法を求めているわけではありません。私が求めているのは、 を使用std::map
するよりも を使用する方が明らかに効率的であることをどのように説明できるかということstd::set
です。私はこの現象の仕組みを理解できていないだけで、誰かが何らかの洞察を得ることができることを願っています.
Code1 (マップ、TLE 3 を使用):
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
int main ()
{
string s;
cin >> s;
vector <long long> p;
p.push_back(1);
for (int i = 1; i < s.size(); i++)
p.push_back(31 * p[i - 1]);
vector <long long> hash_temp;
hash_temp.push_back((s[0] - 'a' + 1) * p[0]);
for (int i = 1; i < s.size(); i++)
hash_temp.push_back((s[i] - 'a' + 1) * p[i] + hash_temp[i - 1]);
int n = s.size();
int answer = 0;
for (int i = 1; i <= n; i++)
{
map <long long, bool> hash_ans;
for (int j = 0; j < n - i + 1; j++)
{
if (j == 0)
hash_ans[hash_temp[j + i - 1] * p[n - j - 1]] = true;
else
hash_ans[(hash_temp[j + i - 1] - hash_temp[j - 1]) * p[n - j - 1]] = true;
}
answer += hash_ans.size();
}
cout << answer;
}
Code2 (セット、TLE 2 を使用):
#include <iostream>
#include <string>
#include <vector>
#include <set>
using namespace std;
int main ()
{
string s;
cin >> s;
vector <long long> p;
p.push_back(1);
for (int i = 1; i < s.size(); i++)
p.push_back(31 * p[i - 1]);
vector <long long> hash_temp;
hash_temp.push_back((s[0] - 'a' + 1) * p[0]);
for (int i = 1; i < s.size(); i++)
hash_temp.push_back((s[i] - 'a' + 1) * p[i] + hash_temp[i - 1]);
int n = s.size();
int answer = 0;
for (int i = 1; i <= n; i++)
{
set <long long> hash_ans;
for (int j = 0; j < n - i + 1; j++)
{
if (j == 0)
hash_ans.insert(hash_temp[j + i - 1] * p[n - j - 1]);
else
hash_ans.insert((hash_temp[j + i - 1] - hash_temp[j - 1]) * p[n - j - 1]);
}
answer += hash_ans.size();
}
cout << answer;
}