zoukankan      html  css  js  c++  java
  • [JSOI2009]密码

    题目

    复习( m AC)自动机来了

    一道简单题,转化一些题意就是在( m AC)自动机走一条长度为(L)的路径,使得这条路径经过(n)个不同的目标点

    求方案显然直接搞,设(dp_{i,j,s})表示走了(i)步,目前在( m AC)自动机第(j)个节点,经过的节点的状态为(s),转移显然随便转移

    方案数不超过(42)的时候输出所有方案,显得非常睿智,感觉直接爆搜会(T),于是提前处理一个数组(f_{i,j,s})表示当前这个状态能否到达一个终点,利用这个数组剪枝复杂度就有保证了

    代码

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=255;
    LL dp[2][maxn][1025];
    int s[maxn],fa[maxn],son[maxn][26];
    char S[105];int n,m,L,len,o;
    inline void ins(int x) {
    	scanf("%s",S+1);int len=strlen(S+1);
    	int now=0;
    	for(re int i=1;i<=len;i++) {
    		if(!son[now][S[i]-'a']) son[now][S[i]-'a']=++m;
    		now=son[now][S[i]-'a'];
    	}
    	s[now]|=(1<<(x-1));
    }
    namespace sub {
    	bool f[26][maxn][1025],vis[26][maxn][1025];
    	int b[26];
    	bool find(int l,int x,int h) {
    		if(l==L) {
    			vis[l][x][h]=1;
    			return f[l][x][h]=(h==len-1);
    		}
    		if(vis[l][x][h]) return f[l][x][h];
    		vis[l][x][h]=1;
    		for(re int i=0;i<26;i++) 
    			f[l][x][h]|=find(l+1,son[x][i],h|s[son[x][i]]);
    		return f[l][x][h]; 
    	}
    	inline void out() {
    		for(re int i=1;i<=L;++i) putchar(b[i]+'a');
    		puts("");
    	}
    	void Dfs(int l,int x,int h) {
    		if(!f[l][x][h]) return;
    		if(l==L) {
    			if(h==len-1) out();
    			return;
    		}
    		for(re int i=0;i<26;++i)
    			b[l+1]=i,Dfs(l+1,son[x][i],h|s[son[x][i]]);
    	}
    	inline void solve() {
    		find(0,0,0);Dfs(0,0,0);
    	}
    }
    int main() {
    	scanf("%d%d",&L,&n);
    	for(re int i=1;i<=n;i++) ins(i);
    	std::queue<int> q;
    	for(re int i=0;i<26;++i) if(son[0][i]) q.push(son[0][i]);
    	while(!q.empty()) {
    		int k=q.front();q.pop();
    		s[k]|=s[fa[k]];
    		for(re int i=0;i<26;++i)
    		if(son[k][i]) fa[son[k][i]]=son[fa[k]][i],q.push(son[k][i]);
    		else son[k][i]=son[fa[k]][i];
    	}
    	dp[0][0][0]=1;len=(1<<n),o=0;
    	for(re int i=0;i<L;i++,o^=1) {
    		memset(dp[o^1],0,sizeof(dp[o^1]));
    		for(re int j=0;j<=m;j++) 
    			for(re int k=0;k<len;k++) {
    				if(!dp[o][j][k]) continue;
    				for(re int p=0;p<26;++p)
    				 	dp[o^1][son[j][p]][k|s[son[j][p]]]+=dp[o][j][k];
    			}
    	}
    	LL ans=0;
    	for(re int i=0;i<=m;i++) ans+=dp[o][i][len-1];
    	printf("%lld
    ",ans);
    	if(ans<=42) sub::solve();
    	return 0;
    }
    
  • 相关阅读:
    查看端口号被哪个程序占用
    超出部分用省略号显示 以及 bootStrapTable 的属性一览表
    bootstrap checkbox选中事件
    bootstrap table中formatter作用是什么
    MD5 AES Des 加密解密
    bootstrapTable 隐藏某一列
    报错信息是Error setting null for parameter #1 with JdbcType OTHER
    下拉框隐藏样式,只保留内容
    python学习第二天
    python学习第一天
  • 原文地址:https://www.cnblogs.com/asuldb/p/11574800.html
Copyright © 2011-2022 走看看