zoukankan      html  css  js  c++  java
  • 【纪中集训2019.3.19】不同的缩写

    题意:

    描述

    考虑用(n)个字符串(t_{i})去代替(n)个字符串(s_{i}),满足(t_{i}是s_{i})的子序列且(t_{i})互不相同;

    给出(s_{i}),最小化(max { |t_{i}|});

    范围

    (n,|s_{i}| le 300);

    题解:

    • 随机的情况下答案一般都是1,2;

    • 所以暴力找出所有长度为1和2的子序列进行匹配可以得到一部分分;

    • 二分答案(mid)

    • (dfs)找到所有长度小于等于(mid)的子序列连边,做二分图匹配;

    • 当一个点找到的不相同的子序列超过(n)个时一定有匹配,就不需要再继续(dfs)了;

    • 所以最多一共(n^2)个点,(n^2)条边;

    • 期望复杂度:(O(log n n^2sqrt{n^2}) = O(n^3 log n));

    • 常数较小;

      #include<bits/stdc++.h>
      using namespace std;
      const int N=310,M=1000010;
      int n,sz,l[N],nxt[N][N][26],mid,cur,cnt,T,vis[M],p[M],q[N];
      int ch[M][26],fa[M],fm[M];
      char s[N][N];
      vector<int>g[N];
      void print(int x){
      	if(fa[x])print(fa[x]);
      	putchar(fm[x]+'a');
      }
      bool match(int u){
      	for(int i=0;i<g[u].size();++i){
      		int v=g[u][i];
      		if(vis[v]==T)continue;
      		vis[v]=T;
      		if(!p[v]||match(p[v])){
      			p[v]=u;q[u]=v;
      			return true;
      		}
      	}
      	return false;
      }
      int CH(int x,int y){
      	if(ch[x][y])return ch[x][y];
      	ch[x][y]=++sz;
      	memset(ch[sz],0,sizeof(ch[sz]));
      	fm[sz]=y;fa[sz]=x;p[sz]=0;
      	return sz;
      }
      void dfs(int t,int x,int y){
      	if(cnt==n)return;
      	if(y)g[t].push_back(cur),++cnt;
      	if(y==mid)return;
      	for(int i=0;i<26;++i)if(nxt[t][x][i]<=l[t]){
      		cur=CH(cur,i);
      		dfs(t,nxt[t][x][i],y+1);
      		cur=fa[cur];
      		if(cnt==n)break;
      	}
      }
      bool check(){
      	sz=0;
      	memset(ch[0],0,sizeof(ch[0]));
      	for(int i=1;i<=n;++i){
      		g[i].clear();
      		cur=cnt=0;
      		dfs(i,0,0);
      	}
      	++T;for(int i=1;i<=n;++i,++T)
      	if(!match(i))return false;
      	return true;
      }
      int main(){
      	freopen("diff.in","r",stdin);
      	freopen("diff.out","w",stdout);
      	scanf("%d",&n);
      	int mx=0;
      	for(int i=1;i<=n;++i){
      		scanf("%s",s[i]+1);
      		l[i]=strlen(s[i]+1);
      		for(int j=0;j<26;++j)nxt[i][l[i]][j]=l[i]+1;
      		for(int j=l[i]-1;~j;--j){
      			memcpy(nxt[i][j],nxt[i][j+1],sizeof(nxt[i][j]));
      			nxt[i][j][s[i][j+1]-'a']=j+1;
      		}
      		mx=max(mx,l[i]);
      	}
      	int L=0,R=mx;
      	while(L<R){
      		mid=L+R>>1;
      		if(check())R=mid;
      		else L=mid+1;
      	}
      	mid=L;
      	if(!check())puts("-1"),exit(0);else printf("%d
      ",L);
      	for(int i=1;i<=n;++i)print(q[i]),putchar('
      ');
      	return 0;
      }
      
  • 相关阅读:
    about paper
    虚拟环境部署过程中遇到的问题
    201621123028《Java程序设计》第4周学习总结
    Linux C 数据结构 ->单向链表<-(~千金散尽还复来~)
    Spring 解析(获取)URL 参数
    【简单】罗马数字转整数
    【简单】字符串字母数统计
    MongoDB 集合(collection)常用方法 (Method)
    python中group()函数的用法
    requests库
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10560554.html
Copyright © 2011-2022 走看看