• CF1400F


    1400F - x-prime Substrings

    首先发现 (x) 很小,所以发现对应的 x-prime 字符串数也很少,最多的情况是 (x = 19),有 2399 个,先爆搜出来。

    现在问题变成了,删去最少的字符,使字符串内没有这些模式串。

    那么建 AC 自动机,把模式串终点标记,即在非终点行走,每次可以跳过字符,求跳过的最小值。

    DP 一下,设 (f_{i, u}) 为前 (i) 个字符,当前在 AC 自动机上的 (u) 号节点,其中没有 x-prime 子串,删除字符的最小值。

    • 有边 ((u, v)),即从 (u)(s[i + 1]) 字符到 (v),若 (v) 点合法,即 (f_{i + 1, v} = f_{i, u})
    • 也可以不走,原地不动,(f_{i + 1, u} = f_{i, u} + 1)

    滚动数组可以滚掉第一维,这样空间就够了。最坏 (x = 19) 时 AC 自动机有 5000 左右的点数。

    最坏复杂度 (5000 imes 1000 = 5 imes 10^6)。跑得过。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
     
    typedef long long LL;
     
    const int N = 2005, S = 5005, INF = 0x3f3f3f3f;
     
    int n, x, d[N], cnt, tr[S][9], fail[S];
    int idx, f[S], g[S], q[S];
     
    bool match[S];
     
    char s[N];
     
    bool inline check(int m) {
        for (int i = 1; i <= m; i++) {
            int s = 0;
            for (int j = i; j <= m; j++) {
                s += d[j];
                if (s != x && x % s == 0) return false;
            }
        }
        return true;
    }
     
    void inline insert(int m) {
    	int p = 0;
    	for (int i = 1; i <= m; i++) {
    		int ch = d[i] - 1;
    		if (!tr[p][ch]) tr[p][ch] = ++idx;
    		p = tr[p][ch];
    	}
    	match[p] = true;
    }
     
    void dfs(int u, int rest) {
    	if (!rest) {
    	    if (check(u - 1)) insert(u - 1);
    	    return;
    	}
    	for (int i = 1; i <= min(rest, 9); i++) {
    		d[u] = i;
    		dfs(u + 1, rest - i);
    	}
    }
     
    void inline build() {
    	int hh = 0, tt = -1;
        for (int i = 0; i < 9; i++)
        	if (tr[0][i]) q[++tt] = tr[0][i];
       	while (hh <= tt) {
       		int u = q[hh++];
       		for (int i = 0; i < 9; i++) {
       			int &v = tr[u][i];
       			if (!v) v = tr[fail[u]][i];
       			else fail[v] = tr[fail[u]][i], q[++tt] = v;
       		}
       	}
    }
     
    int main() {
    	scanf("%s%d", s + 1, &x);
    	n = strlen(s + 1);
    	dfs(1, x);
    	build();
    	memset(f, 0x3f, sizeof f); f[0] = 0;
    	for (int i = 1; i <= n; i++) {
    		int ch = s[i] - '1';
    		for (int j = 0; j <= idx; j++) g[j] = f[j], f[j] = INF;
    		for (int j = 0; j <= idx; j++) {
    			if (g[j] != INF) {
    				f[j] = min(f[j], g[j] + 1);
    				int v = tr[j][ch];
    				if (!match[v]) f[v] = min(f[v], g[j]);
    			}
    		}
     	}
     	int ans = 2e9;
     	for (int i = 0; i <= idx; i++) ans = min(ans, f[i]);
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    Django REST Framework
    Django REST Framework 序列化和校验 知识点
    Django REST Framework 数码宝贝
    浏览器的跨域解决方案
    Django Rest Framework 简介及 初步使用
    javaScript
    jQuery 事件流的概念
    jQuery 文档操作
    Django
    crm 系统项目(三) 业务
  • 原文地址:https://www.cnblogs.com/dmoransky/p/13564535.html
Copyright © 2020-2023  润新知