CF427D Match amp; Catch(后缀数组,思维)
发布日期:2021-06-30 10:30:13 浏览次数:3 分类:技术文章

本文共 2620 字,大约阅读时间需要 8 分钟。

求出 S A SA SA数组

h e i g h t [ i ] height[i] height[i]表示排名为 i − 1 i-1 i1的后缀和 i i i的后缀的 l c p lcp lcp

考虑 s a [ i − 2 ]    s a [ i − 1 ]    s a [ i ]    s a [ i + 1 ] sa[i-2]\ \ sa[i-1]\ \ sa[i]\ \ sa[i+1] sa[i2]  sa[i1]  sa[i]  sa[i+1]这四个后缀依靠

h e i g h t [ i − 1 ]    h e i g h t [ i ]    h e i g h t [ i + 1 ] height[i-1]\ \ height[i]\ \ height[i+1] height[i1]  height[i]  height[i+1]联系起来

其中 m i n ( h e i g h t [ i − 1 ] , h e i g h t [ i ] , h e i g h t [ i + 1 ] ) min(height[i-1],height[i],height[i+1]) min(height[i1],height[i],height[i+1])是四个后缀公共的 l c p lcp lcp

考虑最后分别出现在两个串唯一一次的串 s s s

一定是 s a [ i − 1 ] sa[i-1] sa[i1]的前缀是 s s s,而且 s a [ i ] sa[i] sa[i]的前缀也是 s s s

而且 s a [ i − 2 ] sa[i-2] sa[i2]的前缀不是 s s s,而且 s a [ i + 1 ] sa[i+1] sa[i+1]的前缀不是 s s s

这相当于

h e i g h t [ i ] > h e i g h t [ i − 1 ] & & h e i g h t [ i ] > h e i g h t [ i + 1 ] height[i]>height[i-1]\&\&height[i]>height[i+1] height[i]>height[i1]&&height[i]>height[i+1]

这样, m a x ( h e i g h t [ i − 1 ] , h e i g h t [ i + 1 ] ) + 1 max(height[i-1],height[i+1])+1 max(height[i1],height[i+1])+1往后的长度都只在 s a [ i − 1 ] sa[i-1] sa[i1] s a [ i ] sa[i] sa[i]中出现过

此时只需要确认 s a [ i − 1 ] sa[i-1] sa[i1] s a [ i ] sa[i] sa[i]是来自两个不同的串即可

#include 
using namespace std;const int maxn = 2e5+10;int c[maxn],rk[maxn],sa[maxn],x[maxn],y[maxn],height[maxn],m;char a[maxn],b[maxn];void SA(int n){
m = 500; for(int i=1;i<=n;i++) c[x[i]=a[i]]++; for(int i=1;i<=m;i++) c[i] += c[i-1]; for(int i=n;i>=1;i--) sa[c[x[i]]--] = i; for(int k=1;k<=n;k<<=1 ) {
int num = 0; for(int i=n-k+1;i<=n;i++) y[++num] = i; for(int i=1;i<=n;i++) if( sa[i]>k ) y[++num] = sa[i]-k; for(int i=0;i<=m;i++) c[i] = 0; for(int i=1;i<=n;i++) c[x[i]]++; for(int i=1;i<=m;i++) c[i] += c[i-1]; for(int i=n;i>=1;i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0; swap(x,y); num = 1, x[sa[1]] = 1; for(int i=2;i<=n;i++) x[sa[i]] = ( y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k] )?num:++num; if( num==n ) break; m = num; } for(int i=1;i<=n;i++) rk[sa[i]] = i; for(int i=1,k=0;i<=n;i++) {
if( rk[i]==1 ) continue; int j = sa[rk[i]-1]; if( k ) k--; while( i+k<=n&&j+k<=n&&a[i+k]==a[j+k] ) k++; height[rk[i]] = k; }}int main(){
cin >> ( a+1 ) >> ( b+1 ); int len1 = strlen( a+1 ), len2 = strlen( b+1 ); a[len1+1] = '#'; for(int i=1;i<=len2;i++) a[i+1+len1] = b[i]; SA(len1+1+len2); int ans = 1e9; for(int i=2;i<=len1+1+len2;i++) {
if( sa[i-1]<=len1&&sa[i]<=len1 ) continue; if( sa[i-1]>len1+1&&sa[i]>len1+1 ) continue;//需要来自不同的串 if( height[i]>height[i-1]&&height[i]>height[i+1] ) ans = min( ans,max(height[i-1],height[i+1])+1 ); } if( ans==1e9 ) ans = -1; cout << ans;}

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/114401979 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:2020 CCPC Wannafly 纳新一百的石子游戏(NIM博弈原理)
下一篇:QMYSQL driver not loaded driver not loaded(解决方案与libmysql.dll文件下载)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月25日 20时54分44秒