• 【CF1476E】Pattern Matching


    题目

    题目链接:https://codeforces.com/problemset/problem/1476/E
    给定 (n) 个模式串 (p_i)(m) 个字符串 (s_i),其中 (p_i) 两两不同。每个模式串和字符串都包含 (k) 个字符。其中模式串中可以含通配符(用下划线表示,可以匹配任何字符),剩余字符都为小写英文字母。同时给定 (n) 个数 (mt_i),要求重新排列模式串使得 (s_j) 匹配到的第一个模式串为 (p_{mt_j})。请判断是否存在排列方案满足如上要求,能的话请输出方案。
    (n,mleq 10^5;kleq 4)

    思路

    挺无聊的一道缝合题。。。
    发现 (kleq 4),也就是每一个字符串 (s_i) 最多只有 (16) 个模式串 (p) 可以匹配上。所以我们可以把每一个模式串标号,对于每一个字符串枚举所有能和它匹配的模式串,要求这些模式串的编号都必须大于 (mt_i) 的编号。
    那就直接上拓扑排序即可。匹配可以不用 Tire,直接看成一个 27 进制数用数组存即可。(27^4leq 6 imes 10^5)
    时间复杂度 (O(2^knk))

    代码

    #include <bits/stdc++.h>
    #define pYES printf("YES
    ");
    #define pYes printf("Yes
    ");
    #define pyes printf("yes
    ");
    #define pNO printf("NO
    ");
    #define pNo printf("No
    ");
    #define pno printf("no
    ");
    #define mp make_pair
    #define ST first
    #define ND second
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    
    const int N=100010,M=600010;
    int n,m,k,tot,head[N],id[M],deg[N],ans[N];
    char s[N][6],t[6];
    
    struct edge
    {
    	int next,to;
    }e[N*16];
    
    void add(int from,int to)
    {
    	e[++tot]=(edge){head[from],to};
    	head[from]=tot; deg[to]++;
    }
    
    void topsort()
    {
    	tot=0;
    	queue<int> q;
    	for (int i=1;i<=n;i++)
    		if (!deg[i]) q.push(i);
    	while (q.size())
    	{
    		int u=q.front(); q.pop();
    		ans[++tot]=u;
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			int v=e[i].to;
    			deg[v]--;
    			if (!deg[v]) q.push(v);
    		}
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d%d",&n,&m,&k);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%s",s[i]+1);
    		int p=0;
    		for (int j=1;j<=k;j++)
    			p=p*27+((s[i][j]=='_')?0:(s[i][j]-'a'+1));
    		id[p]=i;
    	}
    	for (int i=1,x;i<=m;i++)
    	{
    		scanf("%s",t+1);
    		scanf("%d",&x);
    		int q=0;
    		for (int j=1;j<=k;j++)
    			q=q*27+((s[x][j]=='_')?0:(s[x][j]-'a'+1));
    		bool flag=0;
    		for (int j=0;j<(1<<k);j++)
    		{
    			int p=0;
    			for (int l=1;l<=k;l++)
    				p=p*27+((j&(1<<(l-1)))?0:(t[l]-'a'+1));
    			if (id[p] && p!=q) add(id[q],id[p]);
    				else if (p==q) flag=1;
    		}
    		if (!flag)  { pNO; return 0; }
    	}
    	topsort();
    	if (tot<n) { pNO; return 0; }
    	pYES; 
    	for (int i=1;i<=n;i++)
    		printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    忘记 jumpserver 超级用户密码
    Linux 安装 MySQL-5.7.23
    Linux下MySQL 8.0安装配置
    H3C 端口镜像设置
    node.js+express+jade系列七:富文本编辑框的使用
    node.js+express+jade系列六:图片的上传
    node.js+express验证码的实现
    node.js定时任务:node-schedule的使用
    node.js+express+jade系列五:ajax登录
    node.js+express+jade系列四:jade嵌套的使用
  • 原文地址:https://www.cnblogs.com/stoorz/p/14769883.html
Copyright © 2020-2023  润新知