zoukankan      html  css  js  c++  java
  • BZOJ 1030 [JSOI2007]文本生成器(ac自动机+dp)

    题意

    给你n个串,求长度为m的串的方案数,使得这个串至少包含一个这n个任意一个串

    思路

    转化为求一个也不包含的方案数
    (dp[i][j])为第i个字符,匹配到ac自动机上的j号节点的方案数,显然不能匹配到有结束点的地方
    fail节点的性质:指向当前串的最长后缀所在的节点
    所以当前节点的fail节点为结束点也不行
    所有原本没有的空节点在build的时候会指向根节点
    所以空节点都在dp[i][0]里

    代码

    空间开小了一直wa

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 10007;
    const int maxn = 5e5+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int dp[111][7777];
    int n,m;
    struct AC{
        //局部变量没有默认0!
        int trie[maxn][26];
        int num[maxn];//单词出现次数
        int fail[maxn];
        int vis[maxn];//ask函数用到
        int tot;
    
        //多测可写个init
        void init(){tot=0;mem(vis,-1);mem(trie,0);}
        void add(char *s){
            int root = 0, len = strlen(s+1);
            for(int i = 1; i <= len; i++){
                int x = s[i]-'A';
                if(!trie[root][x])trie[root][x]=++tot;
                root=trie[root][x];
            }
            num[root]++;
            vis[root]=0;
        }
        void build(){
            queue<int>q;
            for(int i = 0; i < 26; 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 < 26; 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];
                }
                vis[now]&=vis[fail[now]];
                //if(vis[fail[now]]==0)vis[now]=0;
            }
        }
    
        void solve(){
            dp[0][0]=1;
            
            for(int i = 0; i < m; i++){
                for(int j = 0; j <= tot; j++){
                    if(vis[j]==0)continue;
                    for(int k = 0; k < 26; k++){
                        int to = trie[j][k];
                        if(vis[to]==0)continue;
                        (dp[i+1][to]+=dp[i][j])%=mod;
                    }
                }
            }
        }
    
    }ac;
    
    char a[maxn];
    int main(){
        ac.init();
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++){
            scanf("%s",a+1);
            ac.add(a);
        }
        ac.build();
        ac.solve();
        int ans = 1;
        for(int i = 1; i <= m; i++){
            ans=ans*26%mod;
        }/*
        for(int j = 0; j <= ac.tot; j++){
            printf("%d %d
    ",j,ac.vis[j]);
    
        }
        for(int i = 0; i <= ac.tot; i++){
            printf("%d:: 
    ",i);
            for(int j = 0; j < 26; j++){
                printf("%d %d
    ",j,ac.trie[i][j]);
            }
        }*/
        /*for(int i = 1; i <= m; i++){
            for(int j = 0; j <= ac.tot; j++){
                printf("%d %d == %d
    ",i,j,dp[i][j]);
            }
        }*/
        for(int i = 0; i <= ac.tot; i++){
            ans=(ans+mod-dp[m][i])%mod;
        }
        printf("%d",ans);
        return 0;
    }
    /*
    10 18
    DCSDG
    DSSF
    SADAV
    DSATWYYH
    FDHFIS
    DFGDFGGD
    SASSSS
    HHEBB
    SFTWRTWW
    ZSDFZDS
     */
    
  • 相关阅读:
    南邮PHP反序列化
    偏移脚本
    nginx配置不当导致的目录遍历下载漏洞-“百度杯”CTF比赛 2017 二月场
    初识smarty
    weblogic nmap扫描脚本
    巅峰极客CTF writeup[上]
    JS调用免费接口根据ip查询位置
    JS调用免费接口根据ip查询位置
    JS一维数组、多维数组和对象的混合使用
    JS一维数组、多维数组和对象的混合使用
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11542363.html
Copyright © 2011-2022 走看看