zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 103 E题 Pattern Matching (字典树+拓扑排序)

    传送门

    题意

    有n个模式串与m个字符串,长度均为k。要求重新排序模式串使得第(i)个字符串依次匹配模式串,第一个被匹配的模式串排序前编号为(mt_i)
    字符串均由小写字母组成,模式串由小写字母和下划线组成,下划线可以和任意字母匹配。
    问:是否存在一种排序方式满足要求,若能则输出任意一种方式。

    数据范围

    [1leq nleq 10^5 ]

    [1leq mleq 10^5 ]

    [1leq kleq 4 ]

    [1leq mt_ileq n ]

    题解

    很显然可以发现,第j个字符串若不能与(mt_j)匹配,直接输出"NO",否则,若可以和(mt_j,x_1,x_2,...)进行匹配,在新排列的模式串中,(x_1,x_2...)要放在(mt_j)后面,即可以用(mt_j)(x_1,x_2...)连边。
    最终即可得到一个图。要想存在一种排序方式,该图一定要是一个有向无环图,要想得到一种排序方式,直接拓扑排序扫一下即可。
    以上部分我比赛时也想到了,结果不知道怎么快速进行匹配。
    注意到k最大只有4,我们可以将一个字符串(不是模式串)拆成(2^k)种情况,即枚举位置将部分字母替换成下划线,再将(2^k)个字符串放入模式串建的字典树里去跑。即可在(O(2^k k))完成匹配。
    这题我一直在想如何处理模式串的下划线,没有转换思维用下划线替换字符串中的字母。
    由于每个点最多只能连15条边,所以建图不用担心内存不够。时间复杂度为(O(nk+mk2^k))

    代码

    /*************************************************************************
    	> File Name: 1.cpp
    	> Author: Knowledge_llz
    	> Mail: 925538513@qq.com 
    	> Blog: https: https://www.cnblogs.com/Knowledge-Pig/ 
    	> Created Time: 2021/2/1 15:25:34
     ************************************************************************/
    
    #include<bits/stdc++.h>
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define LL long long
    #define pb push_back
    #define fi first
    #define se second
    #define pr pair<int,int>
    #define mk(a,b) make_pair(a,b)
    using namespace std;
    int read(){
    	char x=getchar(); int u=0,fg=0;
    	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
    	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
    	return fg?-u:u;
    }
    const int maxx=2e5+10;
    int n,m,k;
    char tmp[5];
    struct Trie{
    	int ch[maxx][30];
    	int val[maxx];
    	int sz;
    	Trie(){ sz=1; memset(ch[0],0,sizeof(ch[0])); }
    	int idx(char c){
    		if(c!='_') return c-'a';
    		else return 26;
    	}
    	void insert(char *s,int v){
    		int u=0;
    		For(i,0,k-1){
    			int c=idx(s[i]);
    			if(!ch[u][c]){
    				memset(ch[sz],0,sizeof(ch[sz]));
    				ch[u][c]=sz++;
    			}
    			u=ch[u][c];
    		}
    		val[u]=v;
    	}
    	int query(char *s,int mode){
    		int u=0;
    		For(i,0,k-1){
    			int c=idx(s[i]);
    			if(mode&1) c=26;
    			mode>>=1;
    			u=ch[u][c];
    		}
    		return val[u];
    	}
    
    
    }trie;
    vector<int>vec[maxx],ans;
    int d[maxx];
    bool vis[maxx];
    void dfs(int id){
    	ans.pb(id);
    	vis[id]=1;
    	for(auto i:vec[id]){
    		--d[i];
    		if(!d[i]) dfs(i);
    	}
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("input.in", "r", stdin);
    	freopen("output.out", "w", stdout);
    #endif
    	n=read(); m=read(); k=read();
    	For(i,1,n){
    		scanf("%s",tmp);
    		trie.insert(tmp,i);
    	}
    	For(i,1,m){
    		int mt; bool flag=0;
    		scanf("%s%d",tmp,&mt);
    		For(i,0,15){
    			int u=trie.query(tmp,i);
    			if(!u) continue;
    			if(u!=mt){ vec[mt].pb(u); ++d[u]; }
    			else flag=1;
    		}
    		if(!flag){ printf("NO
    "); return 0; }
    	}
    	For(i,1,n) if(!d[i] && !vis[i])  dfs(i);
    	if(ans.size()!=n) printf("NO
    ");
    	else{
    		printf("YES
    ");
    		for(auto i:ans) printf("%d ",i);
    	}
    	return 0;
    }
  • 相关阅读:
    Linux(debian)安装Redis教程
    Linux下Nginx学习笔记
    Linux常用命令
    MySQL代码片段
    MySql学习笔记
    漂亮的Web颜色
    Electron开发问题总结
    Git 教程
    Python基础
    【原创】servlet+spring+mybatis配置总结
  • 原文地址:https://www.cnblogs.com/Knowledge-Pig/p/14357263.html
Copyright © 2011-2022 走看看