codeforces 427 D Match & Catch ( 后缀数组 )
来源:互联网 发布:手机淘宝换回默认皮肤 编辑:程序博客网 时间:2024/05/16 13:03
题意 : 给你两个字符串 , 找到其中最短的字符串,要求在串1中出现过,在串2中出现过,并且在串1中只出现过一次,在串2中只出现过一次
思路 : 将两个串拼接在一起 , 用 $ 隔开 。 我们根据 height 数组求解。
首先 , 我们要求解的字符串必然是两个串的公共子串 , 所以对于 height[i] 应该要保证 sa[i-1] 和 sa[i] 分别处于两个字符串。( 我们只用考虑后缀排序后相连的情况 , 因为如果两个后缀在sa中不相连,那么中间必然两个字符串的LCP大于这两个字符串的LCP,那么就不能保证这个字符串在两个串中只出现一次了 )
当然这样只是求得两个串的公共子串,要判断是否满足题意,那么就要判断height[i-1] 和 height[i+1] , 只有这两个最大值要小于 height[i] , height[i] 这个字符串才满足题意。否则必然在串1或者串2中出现过该串。
当然了这样求得的字符串不能保证是最短的。对于一个height[i] , 我们取的最小值应该是 max( height[i-1] , height[i+1] ) + 1 . 因为 max( height[i-1] ,height[i+1] ) 就是和其他后缀的最大LCP,那么加1之后就能保证是唯一的。
那么对于每个符合题意的height[i] 取个最小值即可。这样如果用dc3,就是O(n)的复杂度了 。
#include <stdio.h> #include <string.h> #include <string> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define maxn 10005 int wa[maxn],wb[maxn],wv[maxn],wt[maxn]; typedef long long LL ; 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){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) wt[i]=0; for(i=0;i<n;i++) wt[x[i]=r[i]]++; for(i=1;i<m;i++) wt[i]+=wt[i-1]; for(i=n-1;i>=0;i--) sa[--wt[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++) wt[i]=0; for(i=0;i<n;i++) wt[wv[i]]++; for(i=1;i<m;i++) wt[i]+=wt[i-1]; for(i=n-1;i>=0;i--) sa[--wt[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++; } } 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;i++) { if(k)k--; int j = sa[Rank[i]-1]; while(r[i+k]==r[j+k]) k++ ; height[Rank[i]] = k ; } return; }char str[maxn] ;int r[maxn] , sa[maxn] ; int main(){while( scanf( "%s" , str ) != EOF ) {int l1 = strlen( str ) ;str[l1] = '$' ;str[l1+1] = 0 ;scanf( "%s" , str + l1 + 1 ) ;int len = strlen( str ) ;for( int i = 0 ; i < len ; i ++ ) r[i] = str[i] ;r[len] = 0 ;da( r , sa , len + 1 , 200 ) ;calheight( r , sa , len ) ;int Min = INF ;for( int i = 2 ; i <= len ; i ++ ) {if( ( sa[i-1] - l1 ) * ( sa[i] - l1 ) < 0 && height[i] ) {bool flag = true ;int Max = 0 ;if( height[i-1] >= height[i] ) {flag = false ;}elseMax = max( Max , height[i-1] ) ;if( i < len && height[i+1] >= height[i] ) {flag = false ;}elseMax = max( Max , height[i+1] ) ;if( flag ) {Min = min( Min , Max + 1 ) ;}}}if( Min == INF ){puts( "-1" ) ;} else { printf( "%d\n" , Min ) ;}}return 0 ;}
0 0
- codeforces 427 D Match & Catch ( 后缀数组 )
- CodeForces 427D Match & Catch 后缀数组
- Codeforces 427D Match & Catch 后缀自动机 或 后缀数组
- CodeForces 427 D.Match & Catch(后缀数组)
- Codeforces 427D Match & Catch 后缀自动机
- cf 427D Match & Catch 后缀数组
- Codeforces 427D Match & Catch(后缀自动机)
- CF(427D-Match & Catch)后缀数组应用
- Codeforces 427 D. Match & Catch
- CodeForces 427D-Match & Catch
- CodeForces 427D-Match & Catch
- CodeForces 427D Match & Catch
- CF #244 (Div. 2) D Match & Catch (后缀数组 仅出现一次最短公共子串)
- cf244D. Match & Catch 字符串hash (模板)或 后缀数组。。。
- Codeforces Round #244 (Div. 2) D. Match & Catch
- Codeforces round 244(div.2) D match&catch【字符串hash】
- CF 427D Match & Catch 求最短唯一连续LCS
- codeforces 432D D . Prefixes and Suffixes(后缀数组)
- 基于Bmob的Android即时通讯应用源码
- 反向互补子串
- ThinkPHP许愿池 笔记
- FileItem类的常用方法
- 菜鸟第一次写shell脚本:加法运算
- codeforces 427 D Match & Catch ( 后缀数组 )
- Android实现自动通过GPS定位用户所在地名
- fedora20卸载maxthon
- java中二分查找的总结
- android.os.NetworkOnMainThreadException
- 自定义ViewGroup实现垂直滚动
- Oracle 表空间与数据文件
- Yii Criteria常用方法
- 算法竞赛入门经典(第2版)习题3-11 换低挡装置 Kickdown UVa1588