zoukankan      html  css  js  c++  java
  • 【二分】【字符串哈希】【二分图最大匹配】【最大流】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
    ",l);
    	return 0;
    }
  • 相关阅读:
    语言模型的压缩方法
    推荐算法之 Slope One 算法
    基于内容的推荐(Contentbased Recommendations)
    Txt文件转换为Excel文件
    WebResource 内嵌资源
    多层模态窗口showModalDialog页面提交及刷新
    屏蔽/自定义JavaScript脚本错误
    .net动态显示当前时间
    客户端自动累加
    中国IT管理之窥豹一斑
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7287033.html
Copyright © 2011-2022 走看看