Birthday

题解

首先,我们比较容易地吧这道题转化成图上的最大独立集问题。
对于点 i i i和点 j j j,如果它们之间存在包含关系,那么我们就在它们之间连一条边 ( i , j ) (i,j) (i,j),表示它们不能被同时选择。
显然,我们之后只需要选出最多的点使其不相连接即可。

我们先考虑如何构建出这个图。
这也就意味着我们要去判断字符串与字符串之间的包含关系,我们可以去考虑 A C AC AC自动机。
显然, A C AC AC自动机的包含是可以通过跳 f a i l fail fail链进行判断的。
每个节点的 f a i l fail fail节点代表的串的是原节点代表的串的子串。
所以我们可以尝试对于每个节点都记录下来它经过跳 f a i l fail fail链能够跳到的第一个终止节点是哪一个。
显然,这样我们将一个串上所有节点的第一个跳到的终止节点拿出来,就可以建出偏序关系的 D A G DAG DAG了。
再随便 F l o y e d Floyed Floyed一下,就可以将原图还原出来了。

但得到原图后,我们要怎么求最大独立集呢?
最大独立集显然是等价于反图的最大团,当然,如果你直接求团是过不了的。
根据 D i l w o r t h Dilworth Dilworth定理,我们可以把片集的转化到原图的最小链覆盖上面。
最小链覆盖是可以通过该上下界网络流求出的,注意由于我们是要求最小可行流,所以先跑出可行流后还要从 T T T往 S S S跑一次最大流,让流最小化。
显然,求出这个最小可行流后,我们就可以构造出我们的链覆盖,但怎么将链覆盖转化到独立集上呢?
我们可以尝试在每条链上选择一个点,使得所有点独立。
先将每条链选的点都放在链底,然后 c h e c k check check是否合法,如果不合法就把浅的哪个点往上跳,直到合法为止。
容易发现这样是可以构造出一组合法解的,应该是的。

时间复杂度 O ( ∑ l e n ∣ ∑ ∣ + n 3 + ∣ 网 络 流 ∣ ) O\left(\sum len|\sum| + n^3+|网络流|\right) O(∑len∣∑∣+n3+∣网络流∣)。

源码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define MAXN 10000005
#define MAXM 2005
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
const int mo=1e9+7;
const int INF=0x3f3f3f3f;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1;}return t;}
int n,m,bg[805],ed[805],len[805],a[MAXN],pos[MAXN],fa[805],idx,id[805],cho[805];
int head[MAXM],tot,S,T,SS,TT,cnt,dis[MAXM],cur[MAXM],ip[805][805],bp[805];
bool mp[805][805];char str[MAXN];queue<int>q;
vector<int>vec[805];
struct edge{int to,nxt,flow,op;}e[MAXM*300];
void addEdge(int u,int v,int f){e[++tot]=(edge){v,head[u],f};head[u]=tot;}
void addedge(int u,int v,int f){addEdge(u,v,f);e[tot].op=tot+1;addEdge(v,u,0);e[tot].op=tot-1;
}
struct node{int ch[2],fail,ed;};
class AC_Automaton{private:node tr[MAXN];int tot;public:void init(){++tot;}void insert(int l,int r,int od){int now=1;for(int i=l;i<=r;i++){if(!tr[now].ch[a[i]])tr[now].ch[a[i]]=++tot;pos[i]=now=tr[now].ch[a[i]];}tr[now].ed=od;}void sakura(){while(!q.empty())q.pop();tr[1].fail=1;for(int i=0;i<2;i++)if(!tr[1].ch[i])tr[1].ch[i]=1;else tr[tr[1].ch[i]].fail=1,q.push(tr[1].ch[i]);while(!q.empty()){int u=q.front();q.pop();if(!tr[u].ed)tr[u].ed=tr[tr[u].fail].ed;for(int i=0;i<2;i++)if(!tr[u].ch[i])tr[u].ch[i]=tr[tr[u].fail].ch[i];else tr[tr[u].ch[i]].fail=tr[tr[u].fail].ch[i],q.push(tr[u].ch[i]);}for(int i=1;i<=n;i++){for(int j=bg[i];j<=ed[i];j++){int x=tr[pos[j]].ed;if(x&&x!=i)mp[i][x]=1;}int x=tr[tr[pos[ed[i]]].fail].ed;if(x&&x!=i)mp[i][x]=1;}}
}Tr;
bool bfs(){for(int i=1;i<=cnt;i++)cur[i]=head[i],dis[i]=0;while(!q.empty())q.pop();q.push(S);dis[S]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(dis[v]||!e[i].flow)continue;q.push(v);dis[v]=dis[u]+1;if(v==T)return 1;}}return 0;
}
int dfs(int u,int maxf){if(u==T)return maxf;int res=0;for(int i=cur[u];i;cur[u]=i=e[i].nxt){int v=e[i].to;if(!e[i].flow||dis[v]!=dis[u]+1)continue;int tmp=dfs(v,min(maxf,e[i].flow));maxf-=tmp;res+=tmp;e[i].flow-=tmp;e[e[i].op].flow+=tmp;if(!maxf)break;}return res;
}
int sakura(){int res=0;while(bfs())res+=dfs(S,INF);return res;}
void makeSet(int x){for(int i=1;i<=x;i++)fa[i]=i;}
int findSet(int x){return fa[x]==x?x:fa[x]=findSet(fa[x]);}
void unionSet(int x,int y){int u=findSet(x),v=findSet(y);if(u^v)fa[u]=v;}
bool cmp(int x,int y){return len[x]<len[y];}
int main(){read(n);Tr.init();int summ=0;for(int i=1;i<=n;i++){bg[i]=ed[i-1]+1;scanf("%s",str+bg[i]);len[i]=(int)strlen(str+bg[i]);ed[i]=bg[i]+len[i]-1;for(int j=bg[i];j<=ed[i];j++)a[j]=str[j]-'a';Tr.insert(bg[i],ed[i],i);summ+=len[i];}Tr.sakura();for(int i=1;i<=n;i++)for(int k=1;k<=n;k++)if(mp[i][k])for(int j=1;j<=n;j++)if(mp[k][j])mp[i][j]=1;cnt=n+n;SS=++cnt;TT=++cnt;S=++cnt;T=++cnt;for(int i=1;i<=n;i++){addedge(SS,i,1),addedge(i,T,1),addedge(i+n,TT,1),addedge(S,i+n,1);for(int j=1;j<=n;j++)if(mp[i][j])addedge(i+n,j,1),ip[i][j]=tot;}addedge(TT,SS,INF);int tmp=sakura();makeSet(n);e[tot].flow=e[tot-1].flow=0;S=TT;T=SS;tmp+=sakura();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(e[ip[i][j]].flow)unionSet(i,j);for(int i=1;i<=n;i++)if(i==findSet(i))id[i]=++idx;for(int i=1;i<=n;i++)vec[id[findSet(i)]].pb(i);for(int i=1;i<=idx;i++)sort(vec[i].begin(),vec[i].end(),cmp);while(1){bool flag=0;for(int i=1;i<=idx;i++)cho[i]=vec[i][bp[i]];for(int i=1;i<=idx&&!flag;i++)for(int j=1;j<=idx;j++)if(i^j)if(mp[cho[i]][cho[j]]){bp[j]++,flag=1;break;}if(!flag)break;}printf("%d\n",idx);for(int i=1;i<=idx;i++)printf("%d ",cho[i]);puts("");return 0;
}

谢谢!!!

[CF590E]Birthday相关推荐

  1. CF590E-Birthday【AC自动机,最大独立集】

    正题 题目链接:https://www.luogu.com.cn/problem/CF590E 题目大意 nnn个字符串,求一个最大的集合使其中没有任何串是其他集合内字符串的子串 解题思路 先用ACA ...

最新文章

  1. 【Python】Excel处理
  2. vi 查看最顶部_5分钟带你进入 Vim 大门,让你喜欢 Vim
  3. 用户研究,你还在“凭感觉”吗?
  4. 文件跨服务器传输_跨桌面设备传输文件的最优选?
  5. 【Siddhi】Syntax error in SiddhiQL, no viable alternative at input
  6. navicat打开表提示不存在_真相 | 专家提示:“真空轮胎”真的不存在!别再提了...
  7. vue指令02---自动获取焦点(全局自定义指令Vue.directive())和全局过滤器Vue.filter() 的学习...
  8. python3 range函数_为什么python3中的xrange函数不能用
  9. fpga c语言教程,FPGA实践教程(一)用HLS将c程序生成IPcore
  10. 医疗行业的信息化建设
  11. catia制作物料明细_CATIA课时:符合GB的物料清单模板设置视频教程_翼狐网
  12. Mybatis 事务管理器 TransactionManager
  13. python出现无法定位序数于动态链接库ssleay32.dll的问题
  14. web前端基础——媒体查询
  15. 机器学习PAI为你自动写歌词,妈妈再也不用担心我的freestyle了(提供数据、代码)...
  16. e几个灯同时亮灭两次verilog_第7章Verilog设计的层次与风格.PPT.ppt
  17. mysql水果销售系统数据库_mysql数据库水果销售系统
  18. Qemu kvm_qemu详细教程
  19. WebRTC音视频之噪音消除功能
  20. 七牛云存储java上传图片

热门文章

  1. 游戏搭建步骤,自己怎么开发qp软件
  2. Zookeeper笔记(二)Paxos算法与Zookeeper的工作原理
  3. 我的技术BLOG:http://hi.baidu.com/pass86
  4. 浅谈可移植激励规范(PSS)复用策略
  5. [CTF]SCTF2021 WEB复现(详细版)
  6. 记录Blynk的使用日记-《小鱼缸那些事001》
  7. Azure104题库下载2021最新版
  8. 2月券商App行情刷新及交易体验报告,东方与安信升至领导者象限
  9. 预付费系统在农贸市场是如何应用的
  10. 2021SC@SDUSC-PALISADE(九)BGV的API分析