[Template]省选复习计划

[Template]省选复习计划


字符串相关

KMP算法(luogu3375)

740′′

#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)

3242′′

#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 ,然而参考了模板…

第二次 1415′′

#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
859′′

#include <bits/stdc+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值