[Template]省选复习计划
字符串相关
KMP算法(luogu3375)
7′40′′
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005, MAXM = 1005;
char s1[MAXN], s2[MAXM];
int pi[MAXM];
void kmp_init(int len)
{
pi[0] = pi[1] = 0;
int j = 0;
for (int i = 2; i <= len; i++) {
while (j && s2[j+1] != s2[i]) j = pi[j];
if (s2[j+1] == s2[i]) j++;
pi[i] = j;
}
}
void kmp_match(int len)
{
int j = 0, p = strlen(s2+1);
for (int i = 1; i <= len; i++) {
while (j && s1[i] != s2[j+1]) j = pi[j];
if (s1[i] == s2[j+1]) ++j;
if (j == p) printf("%d\n", i-p+1), j = pi[j];
}
}
int main()
{
scanf("%s", s1+1), scanf("%s", s2+1);
kmp_init(strlen(s2+1));
kmp_match(strlen(s1+1));
for (int i = 1, l = strlen(s2+1); i <= l; i++)
printf("%d ", pi[i]);
return 0;
}
AC自动机(hdu2222)
32′42′′
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
int chl[MAXN][26], fail[MAXN], fin[MAXN], top = 0, root = 0, mak[MAXN];
void push(int &nd, char *str)
{
if (!nd) nd = ++top;
if (*str == '\0') fin[nd]++;
else push(chl[nd][*str-'a'], str+1);
}
struct node {
int to, next;
} edge[MAXN];
int head[MAXN], tp = 0;
void push(int i, int j)
{ ++tp, edge[tp] = (node) {j, head[i]}, head[i] = tp; }
queue<int> que;
void init()
{
fail[root] = 0, que.push(root);
while (!que.empty()) {
int tp = que.front(); que.pop();
for (int i = 0; i < 26; i++) {
if (!chl[tp][i]) continue;
int p = fail[tp];
while (p && !chl[p][i]) p = fail[p];
if (p) fail[chl[tp][i]] = chl[p][i];
else fail[chl[tp][i]] = root;
push(fail[chl[tp][i]], chl[tp][i]);
que.push(chl[tp][i]);
}
}
}
void match(int nd, char *str)
{
if (fin[nd]) mak[nd] = 1;
if (*str == '\0') return;
while (nd && !chl[nd][*str-'a']) nd = fail[nd];
if (nd) match(chl[nd][*str-'a'], str+1);
else match(root, str+1);
}
int dp[MAXN], siz[MAXN]; // 两次collect
int dfs1(int nd)
{
if (!nd) return 0;
if (siz[nd] != -1) return siz[nd];
for (int i = 0; i < 26; i++)
mak[nd] |= dfs1(chl[nd][i]);
return siz[nd] = mak[nd];
}
int dfs2(int nd)
{
if (dp[nd] != -1) return dp[nd];
dp[nd] = siz[nd];
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
dp[nd] |= dfs2(to);
}
return dp[nd];
}
char str[MAXN];
int T, n;
void clear()
{
top = root = tp = 0, memset(chl, 0, sizeof chl), memset(fail, 0, sizeof fail);
memset(fin, 0, sizeof fin), memset(mak, 0, sizeof mak);
memset(siz, -1, sizeof siz), memset(dp, -1, sizeof dp);
memset(head, 0, sizeof head);
}
int main()
{
scanf("%d", &T);
while (T--) {
clear();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", str);
push(root, str);
}
init();
scanf("%s", str);
match(root, str);
dfs1(root), dfs2(root);
int ans = 0;
for (int i = 1; i <= top; i++)
ans += dfs2(i)*fin[i];
printf("%d\n", ans);
}
return 0;
}
SA
24′′04′ ,然而参考了模板…
第二次 14′15′′
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+5, N = 1e5;
struct ele {
int k[2], id;
ele(){}
ele(int a, int b, int c) { k[0] = a, k[1] = b, id = c; }
} RE[MAXN], RT[MAXN];
int sa[MAXN], rk[MAXN], height[MAXN], sum[MAXN], n;
char str[MAXN];
void radix_sort()
{
for (int y = 1; y >= 0; y--) {
memset(sum, 0, sizeof sum);
for (int i = 1; i <= n; i++) sum[RE[i].k[y]]++;
for (int i = 1; i <= N; i++) sum[i] += sum[i-1];
for (int i = n; i >= 1; i--) RT[sum[RE[i].k[y]]--] = RE[i];
for (int i = 1; i <= n; i++) RE[i] = RT[i];
}
for (int i = 1; i <= n; i++) {
rk[RE[i].id] = rk[RE[i-1].id];
if (RE[i].k[0] != RE[i-1].k[0] || RE[i].k[1] != RE[i-1].k[1])
rk[RE[i].id]++;
}
}
void calc_sa()
{
for (int i = 1; i <= n; i++) RE[i] = ele(str[i]-'a'+1, 0, i);
radix_sort();
for (int k = 1; k < n; k <<= 1) {
for (int i = 1; i <= n; i++) RE[i] = ele(rk[i], i+k<=n?rk[i+k]:0, i);
radix_sort();
}
for (int i = 1; i <= n; i++) sa[rk[i]] = i;
}
void calc_height()
{
int h = 0;
for (int i = 1; i <= n; i++) {
if (rk[i] == 1) h = 0;
else {
int k = sa[rk[i]-1];
if (--h < 0) h = 0;
while (str[i+h] == str[k+h]) h++;
}
height[rk[i]] = h;
}
}
int main()
{
scanf("%s", str+1);
n = strlen(str+1);
calc_sa(), calc_height();
for (int i = 1; i <= n; i++) printf("%d ", sa[i]); puts("");
for (int i = 2; i <= n; i++) printf("%d ", height[i]);
return 0;
}
SAM
luogu2852
8′59′′
#include <bits/stdc+