zoukankan      html  css  js  c++  java
  • [JSOI2007]文本生成器

    问题描述

    对于一个长度为 \(n\) 的串 \(S\) ,有多少可能情况的串 \(S\) 使得 \(S\) 的子串中至少包含一个给定的串,给定的串有 \(m\)

    解法

    由多模式串匹配想到AC自动机,由计数想到dp

    首先建好Trie图,更新所有end标记。记 \(dp[now][st][flag]\) 表示当前正在匹配第 \(st\) 位,已确定的串匹配到了Trie图上的 \(now\) 号节点,\(flag\) 表示是否已经出现过给定的模式串。总共有 \((\sum_{i=1}^{m} |s_i|)\times n \times 2\) 种状态,显然要记忆化搜索。对于每个状态枚举下一位所有可能的 \(26\) 位字符,并在Trie图上进行节点转移,flag或上end标记,最后累加答案。当 \(st=n+1\) 即已经匹配完成时,返回值为flag的状态(显然若有给定字符串则贡献 \(1\) 的答案)。最终的结果为初始状态 \(dp[0][1][false]\)

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    using namespace std;
    #define Mod 10007
    #define N 107
    
    template<class T>
    inline void read(T &x){
        x=0;char c=getchar();T flag=1;
        while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        x*=flag;
    }
    
    struct Trie{
        int vis[26],fail,end;
    }go[N*100];
    
    int cnt=0,n,m,f[N*100][N][2];
    char s[N];
    queue<int> Q;
    
    inline void insert(){
        int now=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int to=s[i]-'A';
            if(!go[now].vis[to])
                go[now].vis[to]=++cnt;
            now=go[now].vis[to];
        }
        go[now].end=1;
    }
    inline void Get_fail(){
        for(int i=0;i<26;i++)
            if(go[0].vis[i]) Q.push(go[0].vis[i]);
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=0;i<26;i++)
                if(go[u].vis[i]){
                    go[go[u].vis[i]].fail=go[go[u].fail].vis[i];
                    go[go[u].vis[i]].end|=go[go[go[u].fail].vis[i]].end;
                    Q.push(go[u].vis[i]);
                }else go[u].vis[i]=go[go[u].fail].vis[i];
        }
    }
    int dfs(int now,int st,bool flag){
        if(st==m+1) return flag;
        if(f[now][st][flag]!=-1) return f[now][st][flag];
        f[now][st][flag]=0;int ret=0;
        for(int i=0;i<26;i++){
            int to=go[now].vis[i];
            ret=(ret+dfs(to,st+1,flag|go[to].end))%Mod;
        }
        return f[now][st][flag]=ret;
    }
    int main(){
    //    freopen("dict.in","r",stdin);
    //    freopen("dict.out","w",stdout);
        memset(f,-1,sizeof(f));
        read(n);read(m);
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            insert();
        }
        Get_fail();
        printf("%d",dfs(0,1,false));
    }
    /*
    2 2
    AB
    BA
    */
    
  • 相关阅读:
    [转] 64位Oracle 11g R2的客户端连接时报ORA-01019错误
    [转]Oracle11g链接提示未“在本地计算机注册“OraOLEDB.Oracle”解决方法
    [转]通过Net Manager 配置Oracle 11g本地监听服务(listener service)
    [转]jQuery Mobile动态刷新页面样式
    [转]SSIS
    [转]在SSIS中,使用“包配置”时的常见错误与解析
    使用JMH做Java微基准测试
    秒杀系统解决方案
    cookie机制和session机制
    app如何节省流量
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/13550675.html
Copyright © 2011-2022 走看看