HDU - 1403 - Longest Common Substring

先上题目:

Longest Common Substring

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4010    Accepted Submission(s): 1510

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", and the length is 3.

Input

The input contains several test cases. Each test case contains two strings, each string will have at most 100000 characters. All the characters are in lower-case.

Process to the end of file.

Output

For each test case, you have to tell the length of the Longest Common Substring of them.

Sample Input

banana

cianaic

Sample Output

3

  题意:给出两个串,问你这两个串的最长公共子串的长度是多少。

  后缀数组入门题。首先,不得不承认,现在我的水平只可以套一下模板,通过模板我们可以求出sa[],rank[],height[]三个数组。

  对于这里的字符串,我们是从0~n-1。

  sa[i]指的是字典序排第i的后缀的下标是什么,rank[i]指的是原串中第i个后缀(就是从第i个字符开始到末尾的字符串)在后缀数组中排第几。height[i]表示后缀数组中第i个后缀和第i-1一个后缀的最长公共前缀的长度是多少(其中height[0]=0)。

  这里的做法是首先将两个字符串连接起来,在连接处加一个连接符(没在这两个字符串中出现过的字符即可),然后求出height[],再扫描height[],寻找某个同时符合以下要求的值:①比最大值还要大,②suffex(sa[i])和suffex(sa[i-1])分属于两个不同的字符串。这里需要注意每个数组的长度足够。

上代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define MAX 100002
 5 using namespace std;
 6
 7 char s[(MAX<<1)],b[MAX];
 8 int sa[MAX<<1],rank[MAX<<1],height[MAX<<1],t[MAX<<1],t2[MAX<<1],c[MAX<<1],n,li;
 9 int f[(MAX<<1)];
10
11 void build_sa(int m){
12     int i,*x=t,*y=t2;
13     for(i=0;i<m;i++) c[i]=0;
14     for(i=0;i<n;i++) c[x[i]=s[i]]++;
15     for(i=0;i<m;i++) c[i]+=c[i-1];
16     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
17     for(int k=1;k<=n;k<<=1){
18         int p=0;
19         for(i=n-k;i<n;i++) y[p++]=i;
20         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
21         for(i=0;i<m;i++) c[i]=0;
22         for(i=0;i<n;i++) c[x[y[i]]]++;
23         for(i=0;i<m;i++) c[i]+=c[i-1];
24         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
25         swap(x,y);
26         p=1;    x[sa[0]]=0;
27         for(i=1;i<n;i++){
28             x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k] ? p-1 : p++;
29         }
30         if(p>=n) break;
31         m=p;
32     }
33     for(i=0;i<n;i++) rank[sa[i]]=i;
34 }
35
36 void getHeight(){
37     int i,j,k=0;
38     for(i=0;i<n;i++){
39         if(k) k--;
40         j=sa[rank[i]-1];
41         while(s[i+k]==s[j+k]) k++;
42         height[rank[i]]=k;
43     }
44 }
45
46 int main()
47 {
48     int maxn;
49     //freopen("data.txt","r",stdin);
50     while(scanf("%s %s",s,b)!=EOF){
51         strcat(s,"&");
52         li=strlen(s);
53         for(int i=0;i<li-1;i++) f[i]=1;
54         strcat(s,b);
55         f[li-1]=0;
56         n=strlen(s);
57         for(int i=li;i<n;i++) f[i]=-1;
58         build_sa(200);
59         getHeight();
60         maxn=0;
61         for(int i=1;i<n;i++){
62             if(maxn<height[i] && f[sa[i-1]]*f[sa[i]]<0){
63                 maxn=height[i];
64             }
65         }
66         printf("%d\n",maxn);
67     }
68     return 0;
69 }

/*1403*/

HDU - 1403 - Longest Common Substring

时间: 2024-07-31 18:14:09

HDU - 1403 - Longest Common Substring的相关文章

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.简单的记忆就是“你排第几”

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

HDU 1403 Longest Common Substring(最长公共前缀)

http://acm.hdu.edu.cn/showproblem.php?pid=1403 题意:给出两个字符串,求最长公共子串的长度. 思路: 刚开始学后缀数组,确实感觉很难,但是这东西很强大,所以必须要学会它,推荐罗穗骞大牛的论文. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #i

hdu1403 Longest Common Substring

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=1403 题目: Longest Common Substring Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6296    Accepted Submission(s): 2249 Problem Description Give

Longest Common Substring(最长公共子序列)

Longest Common Substring Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 37 Accepted Submission(s): 28   Problem Description Given two strings, you have to tell the length of the Longest Common Su

[Algorithms] Longest Common Substring

The Longest Common Substring (LCS) problem is as follows: Given two strings s and t, find the length of the longest string r, which is a substring of both s and t. This problem is a classic application of Dynamic Programming. Let's define the sub-pro

后缀自动机(SAM) :SPOJ LCS - Longest Common Substring

LCS - Longest Common Substring no tags A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the set of lowercase letters. Substring, also called factor, is a consecutive sequence of characters occurrences at

lintcode 中等题:longest common substring 最长公共子串

题目 最长公共子串 给出两个字符串,找到最长公共子串,并返回其长度. 样例 给出A=“ABCD”,B=“CBCE”,返回 2 注意 子串的字符应该连续的出现在原字符串中,这与子序列有所不同. 解题 注意: 子序列:这个序列不是在原字符串中连续的位置,而是有间隔的,如:ABCDE  和AMBMCMDMEM 最长公共子序列是ADCDE 子串:子串一定在原来字符串中连续存在的.如:ABCDEF 和SSSABCDOOOO最长公共子串是ABCD 参考链接,讲解很详细 根据子串定义,暴力破解 public

spoj 1811 LCS - Longest Common Substring (后缀自动机)

spoj 1811 LCS - Longest Common Substring 题意: 给出两个串S, T, 求最长公共子串. 限制: |S|, |T| <= 1e5 思路: dp O(n^2) 铁定超时 后缀数组 O(nlog(n)) 在spoj上没试过,感觉也会被卡掉 后缀自动机 O(n) 我们考虑用SAM读入字符串B; 令当前状态为s,同时最大匹配长度为len; 我们读入字符x.如果s有标号为x的边,那么s=trans(s,x),len = len+1; 否则我们找到s的第一个祖先a,它