/*
其實這題纔是第一次做
但是一直不過,也不知道怎麼回事兒
就去調了那個簡單題做
現在才發現少了main裏面的if
還有ok2 是我之前寫的,但是少了個{}
題意是,在所給的字符串中找一個子串,最少出現m次,求那個最長的串,並輸出最後一次的開始位置
按長度二分,判斷是否符合條件即可
*/
#include<stdio.h>
#include<string.h>
const int maxn=500010;
int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
int sa[maxn],ss[maxn];
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m)//r[0 n-1] sa[0 n-1] 最大值小於m
{
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]]++;//x==rank 難道是統計字符個數
for(i=1; i<m; i++)
ws[i]+=ws[i-1];//加上前一個
for(i=n-1; i>=0; i--)
sa[--ws[x[i]]]=i;//排第[i]的是誰
for(j=1,p=1; p<n; j*=2,m=p)
{
for(p=0,i=n-j; i<n; i++) //變量j是當前字符串的長度,
y[p++]=i;// 數組y保存的是對第二關鍵字排序的結果
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-1],sa[i],j)?p-1:p++;
}
return;
}
int rank[maxn],height[maxn];
void calheight(int *r,int *sa,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++)
;
return;
}
int pos;
int po;
int ok2(int chang,int ci,int len)
{
po=-1;
int zui=-1,f=0;
int i,jishu=0;
for(i=2;i<=len;++i)
{
if(height[i]>=chang)
{
jishu++;
if(sa[i-1]>=zui) zui=sa[i-1];
if(sa[i]>zui) zui=sa[i];
if(jishu>=ci){ f=1;//少了這個括號
if(zui>po) po=zui;}
}else
{
jishu=0;
zui=-1;
}
}
if(f)
{
return 1;
}else{
return 0;
}
}
bool ok(int x, int m,int n) {
int i, flag = 0;
po = -1;
int tm = 0, tt = -1;
for (i=2; i<=n; i++) {
if (height[i] >= x) {
tm++;
if (sa[i-1] > tt) tt = sa[i-1];
if (sa[i] > tt) tt = sa[i];
if (tm >= m) {
flag = 1;
if (tt > po)
po = tt;
}
}
else {
tm = 0;
tt = -1;
}
}
if (flag)
return true;
return false;
}
int main()
{
int m;
while(scanf("%d",&m),m)
{
getchar();
char r[maxn];
gets(r);
int i;
int len=strlen(r);
if (m == 1) {//少了這個
printf("%d %d\n", len, 0);
continue;
}
for(i=0; i<len; ++i)
{
ss[i]=r[i];
}
ss[len]=0;
da(ss,sa,len+1,128);
calheight(ss,sa,len);//爲什麼是len???
int ret =0,hi=len-m+1,low=1,mid,pp;
po=0;
pos=0;
while(hi>=low)
{
mid=(hi+low)/2;
if(ok2(mid,m-1,len))//
{
pp=po;
ret=mid;
low=mid+1;
}else
{
hi=mid-1;
}
}
if(ret)
{
printf("%d %d\n",ret,pp);
}else
{
printf("none\n");
}
}
return 0;
}
hdu 4080 Stammering Aliens - 後綴數組
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.