poj 2774 Long Long Message(后缀数组入门题)

 1 /******************************************************************
 2 题目:     Long Long Message(poj 2774)
 3 链接:     http://poj.org/problem?id=2774
 4 题意:     给两个字符串,找最长的公共子串
 5 算法:     后缀数组
 6 算法思想: 后缀数组就是套模板求先应得数组,这题用到了两个数组,分
 7            别是sa[],height[];sa[i]表示所有后缀按字典数排序后以s[i]
 8            开始的后缀排在第i位。height[i]表示字典数为i和i+1后缀的
 9            的最长串的前缀。
10 *******************************************************************/
11 #include<cstdio>
12 #include<cstring>
13 #include<algorithm>
14 using namespace std;
15
16 const int mx=200100;
17 char st[mx];
18 int s[mx],sa[mx],t[mx],t2[mx],c[mx],n;
19 int rank[mx],height[mx];
20
21 void build_sa(int m)
22 {
23     int i,*x=t,*y=t2;
24     for (i=0;i<m;i++) c[i]=0;
25     for (i=0;i<n;i++) c[x[i]=s[i]]++;
26     for (i=1;i<m;i++) c[i]+=c[i-1];
27     for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
28     for (int k=1;k<=n;k<<=1)
29     {
30         int p=0;
31         for (i=n-k;i<n;i++) y[p++]=i;
32         for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k;
33         for (i=0;i<m;i++) c[i]=0;
34         for (i=0;i<n;i++) c[x[y[i]]]++;
35         for (i=1;i<m;i++) c[i]+=c[i-1];
36         for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
37         swap(x,y);
38         p=1;
39         x[sa[0]]=0;
40         for (i=1;i<n;i++)
41         x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
42         if (p>=n) break;
43         m=p;
44     }
45 }
46
47 void getHeight()
48 {
49     int i,j,k=0;
50     for (i=0;i<n;i++) rank[sa[i]]=i;
51     for (i=0;i<n-1;i++)
52     {
53         if (k) k--;
54         int j=sa[rank[i]-1];
55         while (s[i+k]==s[j+k]) k++;
56         height[rank[i]]=k;
57     }
58 }
59
60 int main()
61 {
62     n=0;
63     int l1,l2;
64     scanf("%s",st);
65     l1=strlen(st);
66     for (int i=0;i<l1;i++) s[n++]=st[i]-‘a‘+1;
67     s[n++]=28;
68     scanf("%s",st);
69     l2=strlen(st);
70     for (int i=0;i<l2;i++) s[n++]=st[i]-‘a‘+1;
71     s[n++]=0;
72     build_sa(30);
73     getHeight();
74     int maxx=0;
75     for (int i=2;i<n;i++)
76     {
77         if (maxx<height[i])
78         {
79             if (sa[i]>=0&&sa[i]<l1&&sa[i-1]>l1)
80             maxx=height[i];
81             if (sa[i-1]>=0&&sa[i-1]<l1&&sa[i]>l1)
82             maxx=height[i];
83         }
84     }
85     printf("%d\n",maxx);
86     return 0;
87 }
时间: 2024-10-12 17:34:53

poj 2774 Long Long Message(后缀数组入门题)的相关文章

poj 2774 Long Long Message 后缀数组基础题

Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 24756   Accepted: 10130 Case Time Limit: 1000MS Description The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him these days: his mother is ge

poj 2774 Long Long Message 后缀数组LCP理解

题目链接 题意:给两个长度不超过1e5的字符串,问两个字符串的连续公共子串最大长度为多少? 思路:两个字符串连接之后直接后缀数组+LCP,在height中找出max同时满足一左一右即可: #include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue&

poj 2774 Long Long Message 后缀数组

点击打开链接题目链接 Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 23327   Accepted: 9566 Case Time Limit: 1000MS Description The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him

POJ 2774 Long Long Message ——后缀数组

[题目分析] 用height数组RMQ的性质去求最长的公共子串. 要求sa[i]和sa[i-1]必须在两个串中,然后取height的MAX. 利用中间的字符来连接两个字符串的思想很巧妙,记得最后还需要空一个位置避免冲突. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set>

Long Long Message 后缀数组入门题

Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 22564   Accepted: 9255 Case Time Limit: 1000MS Description The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him these days:

PKU 2774 Long Long Message (后缀数组练习模板题)

题意:给你两个字符串,求最长公共字串的长度. by:罗穗骞模板 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define M 303 #define inf 0x3fffffff #define maxn 500000 #define ws ww #define rank RANK #define F

hdu1403 后缀数组入门题

//1403 思路:字符串的任何一个子串都是这个字符串的某个后缀的前缀,则求A和B的最长公共子串等价于求A的后缀和B的后缀的最长公共前缀的最大值. 做法:将第二个字符串写在第一个字符串后面,中间用一个没有出现过的字符隔开,再求这个新的字符串的后缀数组. 1 #include "bits/stdc++.h" 2 using namespace std; 3 const int maxn = 1e6 + 10; 4 char str[maxn]; 5 int int_str[maxn];

Poj 1743——Musical Theme——————【后缀数组模板题】

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22499   Accepted: 7679 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the

POJ 2774 Long Long Message (最长公共子串)

Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 27062   Accepted: 11010 Case Time Limit: 1000MS Description The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him these days