zoukankan      html  css  js  c++  java
  • BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    Description

     
           给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
    任务:
    l        读入单词
    l        计算最长公共子串的长度
    l        输出结果
     

    Input

    文件的第一行是整数 n1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000

    Output

    仅一行,一个整数,最长公共子串的长度。

    Sample Input

    3
    abcb
    bca
    acbc

    Sample Output


    先把所有串拼起来,中间用分隔符分开。
    二分答案x,转化为判定是否有一个长度为x的公共子串。
    然后把后缀分组,每组内height都大于等于x。
    只需要判断是否存在一组出现了所有的原串。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 10050
    int ws[N],wa[N],wb[N],wv[N],r[N],sa[N],height[N],rank[N],n,m,T,pos[N],h[10];
    char str[N];
    void build_suffix_array() {
        m=T+27;
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0;i<m;i++) ws[i]=0;
        for(i=0;i<n;i++) ws[x[i]=r[i]]++;
        for(i=1;i<m;i++) ws[i]+=ws[i-1];
        for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
        for(p=j=1;p<n;j<<=1,m=p) {
            for(p=0,i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j;
            for(i=0;i<n;i++) wv[i]=x[y[i]];
            for(i=0;i<m;i++) ws[i]=0;
            for(i=0;i<n;i++) ws[wv[i]]++;
            for(i=1;i<m;i++) ws[i]+=ws[i-1];
            for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
            for(t=x,x=y,y=t,x[sa[0]]=0,i=p=1;i<n;i++) {
                if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1;
                else x[sa[i]]=p++;
            }
        }
        for(i=1;i<n;i++) rank[sa[i]]=i;
        for(i=p=0;i<n-1;height[rank[i++]]=p)
            for(p?p--:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++) ;
    }
    bool full() {
        int i;
        for(i=1;i<=T;i++) if(!h[i]) return 0;
        return 1;
    }
    bool check(int x) {
        int i,j;
        for(i=1;i<n;i++) {
            if(height[i]<x) {
                memset(h,0,sizeof(h));
            }
            h[pos[sa[i]]]++;
            if(full()) return 1;
        }
        return 0;
    }
    int main() {
        scanf("%d",&T);
        int i,j;
        for(i=1;i<=T;i++) {
            scanf("%s",str);
            for(j=0;str[j];j++) r[n]=str[j]-'a'+1,pos[n++]=i;
            r[n++]=26+i;
        }
        n++;
        build_suffix_array();
        int l=0,ri=n+1;
        while(l<ri) {
            int mid=(l+ri)>>1;
            if(check(mid)) l=mid+1;
            else ri=mid;
        }
        printf("%d
    ",l-1);
    }
    
  • 相关阅读:
    【24点游戏】cocos2dx 源码
    『Python题库
    『Python题库
    【python安装】Windows上安装和创建python开发环境
    『Linux基础
    『Linux基础
    『Linux基础
    『Linux基础
    『Linux基础
    『Python基础-14』匿名函数 `lambda`
  • 原文地址:https://www.cnblogs.com/suika/p/8996194.html
Copyright © 2011-2022 走看看