字尾陣列練習1 不可重疊最長重複子串

2022-06-02 09:36:10 字數 3231 閱讀 2402

這道題在之前,一定要先看一下我之前在字尾陣列部落格裡面提到的最長公共字首

poj1743

時間限制: 2 sec  記憶體限制: 128 mb

提交: 207  解決: 81

[提交] [狀態] [討論版] [命題人:admin]

題目描述

然後如果你了解了最長公共字首,那麼我們就提一下這道題和最長公共字首有什麼大關係

求字串中至少重複1次或者且不重疊的最長長度

這裡重複指的是兩個字串對應位置相減的差相等

比如1 2 3 4 5 6 7 8 9 10,最長長度為5,因為子串1 2 3 4 5 和 6 7 8 9 10變化都一樣的

思路:既然要求變化一樣,那麼可以讓原陣列前後相減,然後利用字尾陣列height的性質求子串最長公共字首即可

這題是要在求出相鄰音高之差之後找不重疊(無公共部分)的最長的重複出現過至少兩次的串,

也就是在height陣列中找到乙個連續段,其各項均大於d且sa陣列中的對應段中最大值最小值之差要大於d。找到最大的d即可。

d符合乙個性質,就是小的d都滿足,大的d都不滿足。用二分法找分界線即可。

然後題意也非常清楚了,我們就直接講方法:最長公共字首+字尾陣列+二分

二分是因為我們要找最大的長度,所以要用二分

然後還有乙個要注意的就是:最長公共字首求出來的是高度差,也就是說我們最後結果要加1,因為如果有n個點,就只有n-1個間隙,所以的話要加1才是我們需要的點數

**的實現

(注釋版,可能最主要的就是提及一下高度差獲取的函式的使用吧,如果認真看**應該也沒有什麼問題)

1

/*求字串中至少重複1次或者且不重疊的最長長度

2這裡重複指的是兩個字串對應位置相減的差相等

3比如1 2 3 4 5 6 7 8 9 10,最長長度為5,因為子串1 2 3 4 5 和 6 7 8 9 10變化都一樣的

4思路:既然要求變化一樣,那麼可以讓原陣列前後相減,然後利用字尾陣列height的性質求子串最長公共字首即可*/5

6/*這題是要在求出相鄰音高之差之後找不重疊(無公共部分)的最長的重複出現過至少兩次的串,

7也就是在height陣列中找到乙個連續段,其各項均大於d且sa陣列中的對應段中最大值最小值之差要大於d。找到最大的d即可。

8d符合乙個性質,就是小的d都滿足,大的d都不滿足。用二分法找分界線即可。

*/9 #include10 #include11 #include12 #include13 #include14 #include15

using

namespace

std;

16int sa[20010],rank[20010],rsort[20010

];17

int a[20010],cnt[20010],pos[20010],n,height[20010];/*

處理最長公共字首

*/18

/*定義 height[i]=suffix(sa[i-1])和 suffix(sa[i])的最長公

19共字首,也就是排名相鄰的兩個字尾的最長公共字首

*/20

bool cmp(int x,int y,int k)

21void get_sa(int n,int m)/*

倍增模版

*/22

46if(p==n) break; m=p;47}

48 a[0]=0; sa[0]=0;49

}50void get_he(int n)/*

最長公共字首

*/5160}

61bool check(int k,int

n)6273}

74}75return

false;76

}77intmain()

7888 a[n]=0; n--;

89get_sa(n,maxx); get_he(n);

90int l=1,r=n,ans=0;91

while(l<=r)/*

二分尋找答案

*/92

99else r=mid-1

;100

}101

if(ans<4) printf("

0\n"

);102

else printf("

%d\n

",ans+1

);103

/*因為我們求的是高度差,也就是間隙,所以如果有n個點,就有n-1個間隙,所以最後結果要增加1

*/104

}105

return0;

106 }

tristan code 注釋版

(非注釋版,如果你完全看懂了**,就沒有必要看注釋版的了)

1 #include2 #include3 #include4 #include5 #include6 #include7

using

namespace

std;

8int sa[20010],rank[20010],rsort[20010];9

int a[20010],cnt[20010],pos[20010],n,h[20010

];10

bool cmp(int x,int y,int k)

11void get_sa(int n,int

m) 12

36if(p==n) break; m=p;37}

38 a[0]=0; sa[0]=0;39

}40void get_he(int

n)4150}

51bool check(int k,int

n)5263}

64}65return

false;66

}67intmain()

6878 a[n]=0; n--;

79get_sa(n,maxx); get_he(n);

80int l=1,r=n,ans=1;81

while(l<=r)

8289

else r=mid-1;90

}91if(ans<4) printf("

0\n"

);92

else printf("

%d\n

",ans+1

);93}94

return0;

95 }

tristan code 非注釋版

字尾陣列(不可重疊最長重複子串)

poj 1743 二分答案,把題目變成判定性問題 判斷是否 存在兩個長度為k的子串是相同的,且不重疊。解決這個問題的關鍵還是利用 height陣列。把排序後的字尾分成若干組,其中每組的字尾之間的height值都 不小於k。有希望成為最長公共字首不小於k的兩個字尾一定在同一組。然 後對於每組字尾,只須...

字尾陣列求不可重疊最長重複子串 POJ 1743

不可重疊最長重複子串 pku1743 給定乙個字串,求最長重複子串,這兩個子串不能重疊。演算法分析 這題比上一題稍複雜一點。先二分答案,把題目變成判定性問題 判斷是否存在兩個長度為k 的子串是相同的,且不重疊。解決這個問題的關鍵還是利用height 陣列。把排序後的字尾分成若干組,其中每組的字尾之間...

最長重複子串(可重疊) 字尾陣列

找了半天終於找到乙個可以提交的地方。題解 任何乙個重複子串,都必然是某兩個字尾的最長公共字首。因為,兩個字尾的公共字首,它出現在這兩個字尾中,並且起始位置時不同的,所以這個公共字首必然重複出現兩次以上 可重疊 而任何兩個字尾的最長公共字首為某一段height值中的最小值,所以最大為height值中的...