K-string HDU - 4641 (后缀自动机)

Posted jiaaaaaaaqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K-string HDU - 4641 (后缀自动机)相关的知识,希望对你有一定的参考价值。

K-string

\[ Time Limit: 2000 ms\quad Memory Limit: 131072 kB \]

题意

给出长度为 \(n\) 的字符串,接下来跟着 \(m\) 次操作,每次 \(1\) 操作往字符串末尾加一个 \(char\)\(2\) 操作统计字符串中出现次数 \(\geq K\) 的字符串个数。

思路

统计一个字符串出现个数,可以用 \(dp[father] = \sum dp[u]\),来计算,那么我们可以知道,一个点从本身往根跑的过程,这个 \(dp\) 值是一直在增大的,所以只要跑到某一个地方的 \(dp \geq K\),就可以不往上更新了,这样插入一个字符,更新一次,边更新边统计答案就可以了。(数据比较水,这样暴力在全是 \(a\) 的情况下是会 \(T\) 的)
这题我用结构体数组写 \(sam\) 被卡了,最后换了纯数组的 \(sam\)\(emmm\)

/***************************************************************
    > File Name    : a.cpp
    > Author       : Jiaaaaaaaqi
    > Created Time : 2019年06月06日 星期四 00时14分49秒
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

struct Sam 
    int node[maxn][27], fa[maxn], step[maxn];
    int dp[maxn];
    int sz, last, K, ans;
    int newnode() 
        mes(node[++sz], 0);
        fa[sz] = step[sz] = 0;
        dp[sz] = 0;
        return sz;
    
    void init() 
        ans = sz = 0;
        last = newnode();
    
    void insert(int k) 
        int p = last, np = last = newnode();
        step[np] = step[p]+1;
        for(; p&&!node[p][k]; p=fa[p])
            node[p][k] = np;
        if(p==0) 
            fa[np] = 1;
         else 
            int q = node[p][k];
            if(step[q] == step[p]+1) 
                fa[np] = q;
             else 
                int nq = ++sz;
                memcpy(node[nq], node[q], sizeof(node[q]));
                dp[nq] = dp[q];
                fa[nq] = fa[q];
                step[nq] = step[p]+1;
                fa[np] = fa[q] = nq;
                for(; p&&node[p][k]==q; p=fa[p])
                    node[p][k] = nq;
            
        
    
    void update(int p) 
        for(; p&&dp[p]<K; p=fa[p]) 
            dp[p]++;
            if(dp[p]>=K)    ans+=step[p]-step[fa[p]];
        
    
 sam;
char s[50005];

int main() 
    while(~scanf("%d%d%d", &n, &m, &sam.K)) 
        scanf("%s", s+1);
        sam.init();
        int len = strlen(s+1);
        for(int i=1; i<=len; i++) 
            sam.insert(s[i]-'a'+1);
            sam.update(sam.last);
        
        char ss[5];
        while(m--) 
            int id;
            scanf("%d", &id);
            if(id == 1) 
                scanf("%s", ss+1);
                sam.insert(ss[1]-'a'+1);
                sam.update(sam.last);
             else 
                printf("%d\n", sam.ans);
            
        
    
    return 0;

以上是关于K-string HDU - 4641 (后缀自动机)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4641 K-string 后缀自动机 并查集

hdu4622(后缀自动机模板)

HDU 4622 Reincarnation(后缀自动机)

HDU4622Reincarnation(后缀自动机)

hdu4622-Reincarnation(后缀自动机)

HDU 4622 Reincarnation 后缀自动机