POJ 2774 Long Long Message
来源:互联网 发布:win10点网络图标没反应 编辑:程序博客网 时间:2024/05/20 21:45
http://poj.org/problem?id=2774
题意:给定两个字符串 A 和 B ,求最长公共子串。
思路:后缀数组。(摘自罗穗骞的国家集训队论文)字符串的任何一个子串都是这个字符串的某个后缀的前缀。求 A 和 B 的最长公共子串等价于求 A 的后缀和 B 的后缀的最长公共前缀的最大值。如果枚举A和 B 的所有的后缀,那么这样做显然效率低下。由于要计算 A 的后缀和 B 的后缀的最长公共前缀,所以先将第二个字符串写在第一个字符串后面,中间用一个没有出现过的字符隔开,再求这个新的字符串的后缀数组。观察一下,看看能不能从这个新的字符串的后缀数组中找到一些规律。以 A=“ aaaba ”,B=“ abaa ”为例,如图 8 所示。
代码:
#include<stdio.h>#include<string.h>#define MAXN 200010#define MAX(a,b) (a) > (b) ? (a): (b) int num[MAXN] ;char str[MAXN] ;int len1 , len2 ,N,M;int sa[MAXN] , rank[MAXN] ,height[MAXN] ;int wa[MAXN] , wb[MAXN] ,wv[MAXN],wd[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 n,int m){//O(NlogN)int i, j , p , *x=wa, *y=wb,*t ;for( i = 0 ; i < m ; i++ ) wd[i] = 0 ;for( i = 0 ; i < n ; i++ ) wd[x[i]=r[i]] ++ ;for( i = 1 ; i < m ; i++ ) wd[i] += wd[i-1] ;for( i = n-1 ;i >= 0 ; i-- ) sa[--wd[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++)wd[i] = 0 ;for( i = 0 ; i < n ; i++)wd[wv[i]] ++ ;for( i = 1 ; i < m ; i++)wd[i] += wd[i-1] ;for( i = n-1 ; i >= 0 ; i--)sa[ --wd[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++;} }} void calHeight(int *r , 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++) ;}}int main(){int k ;while(scanf("%s",str) == 1){len1 = strlen(str);k = 0 ;for(int i=0;i<len1;i++){num[k++] = str[i] - 'a' + 2 ;}num[k++] = 0 ;//想到于'#' scanf("%s",str);len2 = strlen(str);for(int i=0;i<len2;i++)num[k++] = str[i] - 'a' + 2 ;N = len1 + len2 ;M = 30;DA(num,N+1,M);calHeight(num,N);int ans = 0 ;for(int i=2;i<=N;i++){if( (sa[i]<len1&&sa[i-1]>len1) || (sa[i]>len1&&sa[i-1]<len1) ){ans = MAX(ans , height[i]);}}printf("%d\n",ans);}return 0 ;}
- poj 2774 Long Long Message
- POJ 2774 Long Long Message
- poj 2774 Long Long Message
- poj 2774 Long Long Message
- POJ 2774 Long Long Message
- POJ-2774-Long Long Message
- POJ 2774 Long Long Message
- POJ 2774 Long Long Message
- poj 2774 Long Long Message
- poj 2774 Long Long Message
- poj 2774 Long Long Message
- POJ 2774 Long Long Message
- POJ 2774 Long Long Message
- POJ 2774 Long Long Message
- POJ 2774 Long Long Message
- POJ - 2774 Long Long Message
- POJ 2774Long Long Message
- poj 2774 Long Long Message
- C#:一个增强的TcpClient(三)读取
- window.location详解
- C#:一个增强的TcpClient(四)查询
- qt 静态编译
- Java英文面试测试
- POJ 2774 Long Long Message
- linux下repair filesystem模式修复方法实践
- 关于C#[StructLayout(LayoutKind.Sequential)]的问题
- VC 获取汉字拼音首字母(unicode编码)下
- 一天一点学习Linux之在RHEL6系统上配置磁盘阵列(RAID)
- Qt将ttf文件设置为默认字体
- 启动数据库时,遇到ORA-19809错误 .
- Disk management,winhex删除磁盘raid信息
- 定义和实现接口