• F. x-prime Substrings(ac自动机+朴素dp)


    题:https://codeforces.com/contest/1400/problem/F

    题意:给定只含有1~9的字符串s,问最少删除多少个字符能让字符串不含x-prime Substrings(定义见题面)

    分析:因为x<=20所以可以将所有x-prime Substrings找出来(x==20时只有29个),加到ac自动机上;

       然后就在trie树上进行dp转移,dp[i]表示 i 节点的最小值,用二维转移即可

    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<string>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int M=1e6+6;
    const int inf=0x3f3f3f3f;
    int trie[M][12];
    int cntword[M];
    int fail[M];
    int cnt=0,x;
    int dp[2][M];
    vector<int>a;
    
    void insert(){
        int root = 0;
        for(auto it:a){
            int next=it;
            if(!trie[root][next])
                trie[root][next] = ++cnt;
            root = trie[root][next];
        }
        cntword[root]++;
    }
    void getfail(){
        queue <int>q;
        for(int i=0;i<10;i++){
            if(trie[0][i]){
                fail[trie[0][i]] = 0;
                q.push(trie[0][i]);
            }
        }
    
        while(!q.empty()){
            int now = q.front();
            q.pop();
    
            for(int i=0;i<10;i++){
                if(trie[now][i]){
    
                    fail[trie[now][i]] = trie[fail[now]][i];
                    q.push(trie[now][i]);
                }
                else
                    trie[now][i] = trie[fail[now]][i];
            }
        }
    }
    
    void dfs(int now){
        if(now==x){
            int n=a.size();
            int f=1;
            for(int i=0;i<n;i++){
                int sum=0;
                for(int j=i;j<n;j++){
                    sum+=a[j];
                    if(x%sum==0&&sum<x){///满足条件的x-prime Substrings
                        f=0;
                        break;
                    }
                }
            }
            if(f)
                insert();
            return ;
        }
        for(int i=1;i<10&&now+i<=x;i++){
            a.push_back(i);
            dfs(now+i);
            a.pop_back();
        }
    }
    char s[M];
    int main(){
        scanf("%s%d",s,&x);
        dfs(0);
        getfail();
    
        int len=strlen(s);
        for(int i=0;i<=cnt;i++)
            dp[0][i]=dp[1][i]=inf;
        dp[0][0]=0;
        int cur,nex;
        for(int i=0;i<len;i++){
            cur=i&1,nex=cur^1;
            for(int j=0;j<=cnt;j++)
                dp[nex][j]=inf;
            for(int j=0;j<=cnt;j++){
                dp[nex][j]=min(dp[nex][j],dp[cur][j]+1);///先假设要删去当前字符
                int v=trie[j][s[i]-'0'];
                if(!cntword[v])///要是不组成x-prime Substrings,则可无条件转移
                    dp[nex][v]=min(dp[nex][v],dp[cur][j]);
            }
        }
        int ans=inf;
        for(int i=0;i<=cnt;i++)
            ans=min(ans,dp[nex][i]);
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    基于注解的springmvc开发
    判断两数之和
    redux-saga call 和 fork的区别
    滚动轴滚动方向判断
    原生方法scrollTo支持滚动特效
    npm下载包失败的几个原因
    关闭vscode打开新文件自动关闭预览文件功能
    在本地文件当中package.json的作用
    解决crlf 和 lf不同带来的冲突问题
    package-lock.json 文件的作用
  • 原文地址:https://www.cnblogs.com/starve/p/13577608.html
Copyright © 2020-2023  润新知