有一个任务:
最初,我用python编写代码,结果是这样的:
from array import array
def string_xor(a: str, b: str):
"""
Проверка на схожесть строк
3 - одинаковые
2 - 1 различие
1 - больше 2 отличий
"""
k = len(a)
if k == len(b):
a1 = array('u', a)
b1 = array('u', b)
errors = 0
for i in range(k):
if a1[i] != b1[i]:
errors += 1
if errors > 1:
return 1
elif errors == 1:
return 2
elif errors == 0:
return 3
return 1
n, m = map(int, input().split())
words = sorted(input() for _ in range(n))
for _ in range(m):
word = input()
one_diff = [] # Список слов, которые расходятся ровно на одну букву
for cur in words:
ans = string_xor(word, cur)
if ans == 3:
print(cur)
break
elif ans == 2:
one_diff.append(cur)
else:
if one_diff:
print(min(one_diff))
else:
print('?')
但它在其中一项时间测试中崩溃。然后我重写了它的优点,认为它会有所帮助。
#include<iostream>
#include "vector"
#include "algorithm"
using namespace std;
int check(string a, string b) {
int k = a.size();
if (k == b.size()) {
int errors(0);
for (int i = 0; i < k; i++)
errors += a[i] != b[i];
if (errors == 0)
return 0;
else if (errors == 1)
return 1;
return 2;
}
return 2;
}
int main() {
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
string word;
vector <string> words(n), one_diff;
for (string &el : words)
cin >> el;
sort(words.begin(), words.end());
for (int i = 0; i < m; i++) {
cin >> word;
bool is_break(false);
for (const string &cur : words) {
int d = check(cur, word);
if (d == 0) {
cout << cur << "\n";
is_break = true;
break;
}
else if (d == 1)
one_diff.push_back(cur);
}
if (!is_break) {
if (!one_diff.empty()) {
sort(one_diff.begin(), one_diff.end());
cout << one_diff[0] << "\n";
one_diff.clear();
}
else
cout << "?" << "\n";
}
}
}
但它并没有帮助,落在同样的考验。告诉我这里需要更改什么,以便程序及时适应。
我做了一个字符串长度的字典,有一个时间是1.033,它变成了1.09代码:
from array import array
def string_xor(a: str, b: str):
k = len(a)
if k == len(b):
errors = 0
for a1, b1 in zip(a, b):
errors += a1 != b1
if errors > 1:
return 1
elif errors == 1:
return 2
elif errors == 0:
return 3
return 1
n, m = map(int, input().split())
d = {}
for _ in range(n):
word = input()
z = len(word)
d[z] = d.get(z, [word]) + [word]
for i in d.keys():
d[i].sort()
for _ in range(m):
word = input()
one_diff = set()
try:
for cur in d[len(word)]:
ans = string_xor(word, cur)
if ans == 3:
print(cur)
break
elif ans == 2:
one_diff.add(cur)
else:
if one_diff:
print(min(one_diff))
else:
print('?')
except KeyError:
print('?')
PS 代码及时崩溃...
PPS 抱歉,我无法提供该任务的链接。


算法
对于每个字长,都会
k计算k + 1哈希值。一个用于整个单词,其余用于没有一个字母的单词的所有变体。字母没有被划掉,(实际上)被字母表之外的字符代替。所以少碰撞。单词索引放置在手写的哈希表中。表的大小等于字典中所有单词的哈希总数。换句话说,表格中没有空闲单元格。
创建表后,
k + 1会为每个检查的单词计算一个哈希值。检查与哈希相对应的所有单词是否可能相等或相等,而不需要单个字符。字典记忆
所有单词按
20字符排列的字典。文件大小不超过 2MB。那么字数n < 100000。存储一个字的结构需要21每个字的字节数。哈希数2100000 = (1 + 20) * 100000。总计
19MB。一个大小的文件可以容纳的最大单词数
2MB是1 + 26 + 26**2 + 26**3 + 404953 = 423232. 所有长度为 0、1、2 和 3 的不同单词,以及长度为 4 的单词的其余部分。这样的字典将占用423232 * 21 = 8887872内存中的字节。没有了9MB。所需的最大哈希数不超过423232 + 2 * 1024 * 1024 = 2520384. 总内存不超过9MB + 10MB + 10MB = 29MB.表现
对于所有经过测试的字典,在未优化的 GCC 构建上的运行时间不超过一秒。也许缺少了什么。字典测试了 230,000 个单词(最多四个字符)和 50,000 个单词(最多 20 个字符)。速度取决于散列的质量,而散列的质量又必须很快。哈希函数在 Boost 中被监视。
通过在字典中选择单词,您可以尝试减慢程序的速度。最多 20 个字符的单词
2 * 10^28,很明显,对于任何适合 64MB 的哈希表,您都可以选择这样的单词,它们最终都放在一个篮子里。编码
试试这样:
然后对于这样的数据:
将输出以下内容:
对于第二个测试用例:
答案将是:
这是一个特殊的哈希任务。您只需要计算成对字母的哈希值。
也就是有字
还有他们的哈希
并检查字典是否包含:
我制作了自己的版本:
工作速度足够快