poj2774 后缀数组 求最长公共子串

Reference:IOI2009论文

http://www.cnblogs.com/ziyi--caolu/p/3192731.html

 1 #include "stdio.h"
 2 #include "string.h"
 3 #define maxn 200010
 4
 5 int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
 6 int rank[maxn],height[maxn];
 7 int r[maxn],sa[maxn];
 8 char s1[100010],s2[100010];
 9 int n,l1,l2,ans;
10
11 int cmp(int *r,int a,int b,int l)
12 {
13     return r[a]==r[b]&&r[a+l]==r[b+l];
14 }
15
16 void da(int *r,int *sa,int n,int m)
17 {
18     int i,j,p,*x=wa,*y=wb,*t;
19     for(i=0; i<m; i++) ws[i]=0;
20     for(i=0; i<n; i++) ws[x[i]=r[i]]++;
21     for(i=1; i<m; i++) ws[i]+=ws[i-1];
22     for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
23     for(j=1,p=1; p<n; j*=2,m=p)
24     {
25
26         for(p=0,i=n-j; i<n; i++) y[p++]=i;
27         for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
28         for(i=0; i<n; i++) wv[i]=x[y[i]];
29         for(i=0; i<m; i++) ws[i]=0;
30         for(i=0; i<n; i++) ws[wv[i]]++;
31         for(i=1; i<m; i++) ws[i]+=ws[i-1];
32         for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
33         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
34             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
35     }
36     return;
37 }
38
39 void calheight(int *r,int *sa,int n)
40 {
41     int i,j,k=0;
42     for(i=1; i<=n; i++) rank[sa[i]]=i;
43     for(i=0; i<n; height[rank[i++]]=k)
44         for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
45     return;
46 }
47
48 bool _same(int lx,int ly,int l1,int l2)
49 {
50     return (((lx<=l1-1) && (ly>=l1+1))||((ly<=l1-1) && (lx>=l1+1)));
51 }
52
53 //da(r,sa,n+1,128);
54 //calheight(r,sa,n);
55 int main()
56 {
57     scanf("%s",s1);
58     l1=strlen(s1);
59     scanf("%s",s2);
60     l2=strlen(s2);
61     for (int i=0;i<l1;i++)
62     {
63         char ch=s1[i];
64         int tmp=ch-‘a‘+2;
65         r[i]=tmp;
66     }
67     r[l1]=99;
68     for (int i=l1+1;i<l1+l2+1;i++)
69     {
70         char ch=s2[i-l1-1];
71         int tmp=ch-‘a‘+2;
72         r[i]=tmp;
73     }
74     n=l1+l2+1;
75     r[n]=0;
76
77     da(r,sa,n+1,128);
78     calheight(r,sa,n);
79
80     ans=0;
81     for (int i=1;i<=n;i++)
82     {
83         int t1=sa[i],t2=sa[i-1];
84         if (_same(t1,t2,l1,l2))
85         {
86             if (height[i]>ans)
87                 ans=height[i];
88         }
89     }
90     printf("%d\n",ans);
91
92     return 0;
93 }
时间: 2024-08-25 01:29:41

poj2774 后缀数组 求最长公共子串的相关文章

HDU 1403 Longest Common Substring(后缀数组,最长公共子串)

hdu题目 poj题目 参考了 罗穗骞的论文<后缀数组——处理字符串的有力工具> 题意:求两个序列的最长公共子串 思路:后缀数组经典题目之一(模版题) //后缀数组sa:将s的n个后缀从小到大排序后将 排序后的后缀的开头位置 顺次放入sa中,则sa[i]储存的是排第i大的后缀的开头位置.简单的记忆就是“排第几的是谁”. //名次数组rank:rank[i]保存的是suffix(i){后缀}在所有后缀中从小到大排列的名次.则 若 sa[i]=j,则 rank[j]=i.简单的记忆就是“你排第几”

后缀数组 - 求最长公共子序列 + 模板题 : poj 2774

// Memory Time // 1347K 0MS // by : Snarl_jsb // 2014-09-24-19.57 #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack>

SPOJ 687. Repeats(后缀数组求最长重复子串)

题目大意:给你一个串让你求出重复次数最多的连续重复子串的重复次数. 解题思路:论文上给出的解答是: 这还没完,因为经过这两个点的情况还不完备,应还可以假设起点在 [ i*j-i+1, i*j-d],其中 d = i-L/i (d = i-L%i)其意义为根据已知的匹配长度,可以将起点往前移动的范围,太靠后将不能够构造出比之前更好的解.如果要求出某个最多的连续重复子串的最小字典序子需要枚举所有起点,但如果只是要的到最多的重复次数或者任意最多的连续重复子串,那么只需要枚举i*j-d处的起点即可,因为

POJ 3693 Maximum repetition substring(后缀数组求最长重复子串)

题目大意:和spoj687类似,就是当长度相同是需要输出一个最小的字典序的序列. 解体思路:这次需要枚举所有的从i到d = i-L/i (d = i-L%i)的位置,然后记录保证最大值的同时,求出来字典序最小的. Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7418   Accepted: 2217 Description The repetition numb

POJ 2774 后缀数组:求最长公共子串

思路:其实很简单,就是两个字符串连接起来,中间用个特殊字符隔开,然后用后缀数组求最长公共前缀,然后不同在两个串中,并且最长的就是最长公共子串了. 注意的是:用第一个字符串来判断是不是在同一个字符中,刚开始用了第二个字符的长度来判断WA了2发才发现. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<

poj 2774 Long Long Message,后缀数组,求最长公共子串 hdu1403

题意:给出两个字符串,求最长公共子串的长度. 题解:首先将两个字符串连在一起,并在中间加一个特殊字符(字串中不存在的)分割,然后两个串的最长公共字串就变成了所有后缀的最长公共前缀.这时就要用到height数组,因为任意两个后缀的公共前缀必定是某些height值中的最小值,而这个值如果最大则一定是height中的最大值.在此题中还要注意height最大一定要在两个值所代表的后缀分属不同的字符串地前提下. #include<cstdio> #include<cstring> #incl

URAL 1517 Freedom of Choice(后缀数组,最长公共字串)

题目 输出最长公共字串 #define maxn 200010 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];}//yuan lai zhi qian ba zhe li de l cuo dang cheng 1 le ... void da(int *r,int *sa,int n,int m) { int i,j

HDU 1403 Longest Common Substring(后缀数组啊 求最长公共子串 模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1403 Problem Description Given two strings, you have to tell the length of the Longest Common Substring of them. For example: str1 = banana str2 = cianaic So the Longest Common Substring is "ana", a

利用后缀数组(suffix array)求最长公共子串(longest common substring)

摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其重要的优势在于可以编码简单,代码易于理解,适合快速实现. 首先,来说明一下,LCS通常指的是公共最长子序列(Longest Common Subsequence,名称来源参见<算法导论>原书第3版p223),而不是公共最长子串(也称为最长公共子串). 最长公共子串问题是在文本串.模式串中寻找共有的