這道題在之前,一定要先看一下我之前在字尾陣列部落格裡面提到的最長公共字首
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才是我們需要的點數
**的實現
(注釋版,可能最主要的就是提及一下高度差獲取的函式的使用吧,如果認真看**應該也沒有什麼問題)
1tristan code 注釋版/*求字串中至少重複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 }
(非注釋版,如果你完全看懂了**,就沒有必要看注釋版的了)
1 #include2 #include3 #include4 #include5 #include6 #include7tristan code 非注釋版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 }
字尾陣列(不可重疊最長重複子串)
poj 1743 二分答案,把題目變成判定性問題 判斷是否 存在兩個長度為k的子串是相同的,且不重疊。解決這個問題的關鍵還是利用 height陣列。把排序後的字尾分成若干組,其中每組的字尾之間的height值都 不小於k。有希望成為最長公共字首不小於k的兩個字尾一定在同一組。然 後對於每組字尾,只須...
字尾陣列求不可重疊最長重複子串 POJ 1743
不可重疊最長重複子串 pku1743 給定乙個字串,求最長重複子串,這兩個子串不能重疊。演算法分析 這題比上一題稍複雜一點。先二分答案,把題目變成判定性問題 判斷是否存在兩個長度為k 的子串是相同的,且不重疊。解決這個問題的關鍵還是利用height 陣列。把排序後的字尾分成若干組,其中每組的字尾之間...
最長重複子串(可重疊) 字尾陣列
找了半天終於找到乙個可以提交的地方。題解 任何乙個重複子串,都必然是某兩個字尾的最長公共字首。因為,兩個字尾的公共字首,它出現在這兩個字尾中,並且起始位置時不同的,所以這個公共字首必然重複出現兩次以上 可重疊 而任何兩個字尾的最長公共字首為某一段height值中的最小值,所以最大為height值中的...