当前位置:编程学习 > C/C++ >>

poj 1743 Musical Theme

题目思路:后缀数组求最长不重叠重复子串

[cpp] 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<string> 
#include<queue> 
#include<algorithm> 
#include<vector> 
#include<stack> 
#include<list> 
//#include<iostream> 
#include<map> 
#define M 1000010 
using namespace std; 
#define inf 0x3f3f3f3f 
#define Max 110 
int max(int a,int b) 

    return a>b?a:b; 

int min(int a,int b) 

    return a<b?a:b; 

int wa[M],wb[M],wv[M],ws[M]; 
int rank[M],sa[M],r[M],dp[32][M],height[M],mm[M]; 
int cmp(int *r,int a,int b,int l) 

    return r[a]==r[b]&&r[a+l]==r[b+l]; 

void da(int n,int m) 

   // ws[0]=0; 
    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(j=1,p=1;p<n;j*=2,m=p) 
    { 
        for(p=0,i=n-j;i<n;i++) y[p++]=i; 
        for(i=0;i<n;i++) if(sa[i]>=j) 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,p=1,x[sa[0]]=0,i=1;i<n;i++) 
        { 
            x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; 
        } 
    } 

void calheight(int n) 

    int i,j,k=0; 
    for(i=1;i<=n;i++) rank[sa[i]]=i; 
    for(i=0;i<n;height[rank[i++]]=k) 
    { 
        for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); 
    } 

int check(int k,int n) 

    int mi=sa[1],ma=sa[1]; 
    for(int i=2;i<=n;i++) 
    { 
        if(height[i]<k) 
        { 
            mi=ma=sa[i]; 
        } 
        else 
        { 
         //   printf("aaa\n"); 
            mi=min(sa[i],mi); 
            ma=max(sa[i],ma); 
         //   printf("i %d mi %d ma %d\n",i,mi,ma); 
            if(ma-mi>=k) 
                return 1; 
 
        } 
    } 
    return 0; 

int main() 

   int i,left,right,pre,now,n,mid; 
    while(scanf("%d",&n),n) 
    { 
        scanf("%d",&pre); 
        n--; 
        for(i=0;i<n;i++) 
        { 
            scanf("%d",&now); 
            r[i]=now-pre+100; 
            pre=now; 
          //  printf("i %d r %d\n",i,r[i]); 
        } 
        r[n]=0; 
        da(n+1,200); 
 
        calheight(n); 
      //   for(i=1;i<=n;i++) 
      //  { 
       //     printf("i %d %d %d\n",i,sa[i],height[i]); 
      //  } 
        left=1;right=n/2; 
        while(left<=right) 
        { 
            mid=(left+right)>>1; 
            if(check(mid,n)) left=mid+1; 
            else 
                right=mid-1; 
        //    printf("mid %d\n",mid); 
        } 
        if(right>=4) printf("%d\n",right+1); 
        else 
            printf("0\n"); 
    } 
    return 0; 

作者:Wings_of_Liberty


补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,