欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Castle

程序员文章站 2022-06-11 09:44:52
...

Castle

KMP
如果集合中有一个字符串 Si长度为i,而且为当前 S 的后缀,那么所有比 i 长度小的都会是 S 的后缀(如果存在于集合),所以求出每个当前 S 的后缀最长匹配前面的长度为多少,再用树状数组或前缀和统计在这长度以内加入了集合的有多少个就行了。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1300000;
int sum[maxn], f[maxn], n, m, op, t;
char s[maxn], c;
bool p[maxn] = {0};

char get_char() {
    char o = ' ';
    while (!(o >= 'a' && o <= 'z')) o = getchar();
    return o;
}

int get_int() {
    char o = ' ';
    while (!(o >= '0' && o <= '9')) o = getchar();
    return o-'0';
}

int main() {
    scanf("%d %d", &n, &m);
    scanf("%s", s+1);
    memset(f, 0, sizeof(f));
    for (int i = 2; i <= n; i++) {
        t = f[i-1];
        while (t && s[i] != s[t+1]) t = f[t];
        if (s[i] == s[t+1]) f[i] = t+1;
        else f[i] = 0;
    }
    while (m--) {
        op = get_int();
        if (op == 1) {
            c = get_char();
            s[++n] = c;
            t = f[n-1];
            while (t && s[n] != s[t+1]) t = f[t];
            if (s[n] == s[t+1]) {
                sum[n] = sum[t+1];
                f[n] = t+1;
            } else f[n] = 0;
        } else if (op == 2) {
            if (!p[n]) {
                p[n] = true;
                sum[n]++;
            }
        } else {
            printf("%d\n", sum[n]);
        }
    }
}