【二分】【字符串哈希】【二分图最大匹配】【最大流】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem I. Minimum Prefix
给你n个字符串,问你最小的长度的前缀,使得每个字符串任意循环滑动之后,这些前缀都两两不同。
二分答案mid之后,将每个字符串长度为mid的循环子串都哈希出来,相当于对每个字符串,找一个与其他字符串所选定的子串不同的子串,是个二分图最大匹配的模型,可以匈牙利或者Dinic跑最大流看是否满流。
一个小优化是对于某个字符串,如果其所有不同的子串数量超过n,那么一定满足,可以直接删去。
卡常数,不能用set,map啥的,采取了用数组记录哈希值,排序后二分的手段进行去重和离散化。
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
#define INF 2147483647
#define MAXN 200301
#define MAXM 800501
int v[MAXM],cap[MAXM],en,first[MAXN],next[MAXM];
int d[MAXN],cur[MAXN];
queue<int>q;
int n,S,T;
void Init_Dinic(){memset(first,-1,sizeof(first)); en=0;}
void AddEdge(const int &U,const int &V,const int &W)
{
v[en]=V; cap[en]=W;
next[en]=first[U]; first[U]=en++;
v[en]=U; cap[en]=0;
next[en]=first[V]; first[V]=en++;
}
bool bfs()
{
memset(d,-1,sizeof(d)); q.push(S); d[S]=0;
while(!q.empty())
{
int U=q.front(); q.pop();
for(int i=first[U];i!=-1;i=next[i])
if(d[v[i]]==-1 && cap[i])
{
d[v[i]]=d[U]+1;
q.push(v[i]);
}
}
return d[T]!=-1;
}
int dfs(int U,int a)
{
if(U==T || !a) return a;
int Flow=0,f;
for(int &i=cur[U];i!=-1;i=next[i])
if(d[U]+1==d[v[i]] && (f=dfs(v[i],min(a,cap[i]))))
{
cap[i]-=f; cap[i^1]+=f;
Flow+=f; a-=f; if(!a) break;
}
if(!Flow) d[U]=-1;
return Flow;
}
int max_flow()
{
int Flow=0,tmp=0;
while(bfs())
{
memcpy(cur,first,sizeof(first));
while(tmp=dfs(S,INF)) Flow+=tmp;
}
return Flow;
}
typedef unsigned long long ull;
const ull base=107;
ull bs[200005],hss[200005],hss2[200005];
char* a[205];
char b[200005];
int tmphss[200005];
bool neednot[205];
int len[205],pps[205],ppsend[205];
bool check(int x){
int pp=0;
Init_Dinic();
memset(neednot,0,sizeof(neednot));
int N=n;
for(int i=1;i<=n;++i){
int last=pp;
pps[i]=last+1;
int FirstPre=min(len[i],x);
ull hs=0;
for(int j=0;j<FirstPre;++j){
hs=hs*base+(ull)a[i][j];
}
hss[++pp]=hs;
for(int j=FirstPre;j<len[i];++j){
hs-=(bs[x-1]*(ull)a[i][j-x]);
hs=hs*base+(ull)a[i][j];
hss[++pp]=hs;
}
for(int j=0;j<FirstPre-1;++j){
hs-=(bs[FirstPre-1]*(ull)a[i][len[i]-FirstPre+j]);
hs=hs*base+(ull)a[i][j];
hss[++pp]=hs;
}
sort(hss+last+1,hss+pp+1);
int Size=0;
for(int j=last+2;j<=pp;++j){
if(hss[j]!=hss[j-1]){
++Size;
}
}
if(Size>n){
--N;
neednot[i]=1;
}
ppsend[i]=pp;
}
for(int i=1;i<=pp;++i){
hss2[i]=hss[i];
}
sort(hss2+1,hss2+pp+1);
S=n+pp+1;
T=n+pp+2;
for(int i=1;i<=n;++i){
if(!neednot[i]){
AddEdge(S,i,1);
for(int j=pps[i];j<=ppsend[i];++j){
if(j==pps[i] || hss[j]!=hss[j-1]){
AddEdge(i,n+lower_bound(hss2+1,hss2+pp+1,hss[j])-hss2,1);
}
}
}
}
for(int i=1;i<=pp;++i){
if(i==1 || hss2[i]!=hss2[i-1]){
AddEdge(i+n,T,1);
}
}
return max_flow()>=N;
}
int main(){
// freopen("i.in","r",stdin);
bs[0]=1;
for(int i=1;i<=200000;++i){
bs[i]=bs[i-1]*base;
}
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",b);
len[i]=strlen(b);
a[i]=new char[len[i]+1];
for(int j=0;j<len[i];++j){
a[i][j]=b[j];
}
}
int l=1,r=*max_element(len+1,len+n+1);
while(l<r){
int mid=(l+r>>1);
if(check(mid)){
r=mid;
}
else{
l=mid+1;
}
}
printf("%d\n",l);
return 0;
}
【二分】【字符串哈希】【二分图最大匹配】【最大流】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem I. Minimum Prefix的更多相关文章
- 【二分图】【并查集】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem L. Canonical duel
给你一个网格(n<=2000,m<=2000),有一些炸弹,你可以选择一个空的位置,再放一个炸弹并将其引爆,一个炸弹爆炸后,其所在行和列的所有炸弹都会爆炸,连锁反应. 问你所能引爆的最多炸 ...
- Codeforces Round #543 (Div. 2) F dp + 二分 + 字符串哈希
https://codeforces.com/contest/1121/problem/F 题意 给你一个有n(<=5000)个字符的串,有两种压缩字符的方法: 1. 压缩单一字符,代价为a 2 ...
- 【哈希表】Ural Championship April 30, 2017 Problem H. Hamburgers
题意:有n群人,每个人有喜欢的汉堡配方:有m家店,给出每家店的每个汉堡的配方,如果存在某个汉堡,其配料表包含某个人喜欢的配方,则这个人喜欢这个汉堡所在的店家.问你对每群人,输出被喜欢的人数最多的店面是 ...
- 【二分】【三分】【计算几何】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem L. Lines and Polygon
题意:给你一个凸多边形,和多次询问,每次询问给你一条直线,问你这条直线与凸包上的顶点的最近距离是多少. 记当前询问的直线的斜率为K, 先找到与这条直线距离最远的两个点: 就把凸包所有的边当做有向直线进 ...
- HDU 1045 - Fire Net - [DFS][二分图最大匹配][匈牙利算法模板][最大流求二分图最大匹配]
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1045 Time Limit: 2000/1000 MS (Java/Others) Mem ...
- 二分图的最大匹配——最大流EK算法
序: 既然是个图,并且求边数的最大值.那么这就可以转化为网络流的求最大流问题. 只需要将源点与其中一子集的所有节点相连,汇点与另一子集的所有节点相连,将所有弧的流量限制置为1,那么最大流 == 最大匹 ...
- 【CodeForces】961 F. k-substrings 字符串哈希+二分
[题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} ...
- 【BZOJ4443】[Scoi2015]小凸玩矩阵 二分+二分图最大匹配
[BZOJ4443][Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或 ...
- 【bzoj3291】Alice与能源计划 模拟费用流+二分图最大匹配
题目描述 在梦境中,Alice来到了火星.不知为何,转眼间Alice被任命为火星能源部长,并立刻面临着一个严峻的考验. 为了方便,我们可以将火星抽象成平面,并建立平面直角坐标系.火星上一共有N个居民点 ...
随机推荐
- textarea输入框实时统计输入字符数
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- It is possible that this issue is resolved by uninstalling an existi
使用真机连接Android Studio测试时出现这样的错误: 解决方法: 设置Android Studio 中Instant Run中的选项为不选中 根据以下路径,找到Instant Run中的选项 ...
- 【Spring事务的事务属性】
大家都知道,Spring的声明式事务是通过事务属性来定义的,而spring的事务属性包含了5个方面:传播行为,隔离级别,是否只读,事务超时,回滚规则: 传播行为 传播行为,是属于事务边界相关的属性,定 ...
- artDialog的一些例子与一些属性的介绍。
1.支持自定义按钮 var dialog = art.dialog({ title: '警告', content: '点击管理按钮将让删除按钮可用', width: '20em', button: [ ...
- nowcoder 提高第六场A题
Solution 60分 因为所有的字母要么全相同要么全不同, 所以两条路径比较字典序只需要比较第一条边就可以, 于是建反图, 在反图上按拓扑序转移就可以. 因为有环, 所以拓扑完入度还是不为0的点答 ...
- P2737 [USACO4.1]麦香牛块Beef McNuggets(完全背包+数论确定上界)
题目链接:https://www.luogu.org/problem/show?pid=2737 题目大意:农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块.奶牛们正在 ...
- POJ 2492 A Bug's Life(带权并查集)
题目链接:http://poj.org/problem?id=2492 题目大意:有n只虫子,m对关系,m行每行有x y两个编号的虫子,告诉你每对x和y都为异性,先说的是对的,如果后面给出关系与前面的 ...
- HDU-5281
Senior's Gun Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- 怎么制作CHM格式电子书
CHM格式的帮助文件相信大家都不陌生,CHM文件形式多样,使用方便,深受大家喜爱. 今天给大家介绍一种把文本文件转换为CHM格式电子书的方法. 前期准备过程 1 下载QuickCHM v2.6文件 去 ...
- 基于rest_framework和redis实现购物车的操作,结算,支付
前奏: 首先,要在主机中安装redis,windows中安装,下载一个镜像,直接进行下一步的安装,安装成功后,在cmd中输入redis-cli 安装python的依赖库: redis 和 ...