【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;
}
原文地址:https://www.cnblogs.com/stoorz/p/14769883.html