輸入 N, NC 和文本串。統計文本中長度為 N 的不同子串數。子串總種類數 ≤ 16,000,000。樣例:3 4 daababac → 5。
將子串視為 NC 進制數:`val = c0*NC^(N-1) + c1*NC^(N-2) + ... + c(N-1)`。
因總種類數 ≤ 1600萬,可用大數組 `hash[]` 做直接定址(Direct Addressing),O(1) 去重。
文本字符任意 ASCII。用 `int map[256]` 將實際出現的字符映射為 1..K (K ≤ NC)。遍歷文本賦值。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
using namespace std;
const int MAXH = 16000000 + 100;
char s[MAXH];
int mapChar[256];
int hashTable[MAXH];
int main() {
int N, NC;
while (~scanf("%d%d", &N, &NC)) {
getchar(); // 吃掉換行
scanf("%s", s);
int len = strlen(s);
memset(mapChar, 0, sizeof(mapChar));
memset(hashTable, 0, sizeof(hashTable));
int charCnt = 0;
for (int i = 0; i < len; i++) {
unsigned char ch = s[i];
if (!mapChar[ch]) mapChar[ch] = ++charCnt;
}
int ans = 0;
for (int i = 0; i + N - 1 < len; i++) {
long long val = 0;
for (int j = i; j < i + N; j++) {
val = val * NC + mapChar[(unsigned char)s[j]];
}
if (!hashTable[val]) {
hashTable[val] = 1;
ans++;
}
}
printf("%d\n", ans);
}
return 0;
}
直接定址數組比 `unordered_map` 快 10 倍以上,無哈希函數開銷、無動態分配,是此題 AC 關鍵。