Hdu 1403(后缀数组)

题目链接

Longest Common Substring

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

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

题意:求两个字符串的最长公共字串。

思路:如果说要求一个字符串中至少出现两次的长度最大的字串,那么结果就是后缀数组中相邻的两个后缀的高度

的最大值。也就是max(lcp[i], lcp[i+1]). 因此可以将两个字符串用一个不会出现的字符连接起来(如$)

Accepted Code:

 1 /*************************************************************************
 2     > File Name: 1403.cpp
 3     > Author: Stomach_ache
 4     > Mail: [email protected]
 5     > Created Time: 2014年08月22日 星期五 09时00分05秒
 6     > Propose: sa + lcp
 7  ************************************************************************/
 8
 9 #include <cmath>
10 #include <string>
11 #include <cstdio>
12 #include <fstream>
13 #include <cstring>
14 #include <iostream>
15 #include <algorithm>
16 using namespace std;
17 /*Let‘s fight!!!*/
18
19 const int MAX_N = 100005 << 1;
20 int n, k;
21 int sa[MAX_N], lcp[MAX_N], rank[MAX_N], tmp[MAX_N];
22
23 bool compare_sa(int i, int j) {
24       if (rank[i] != rank[j]) return rank[i] < rank[j];
25      else {
26         int ri = i + k <= n ? rank[i + k] : -1;
27         int rj = j + k <= n ? rank[j + k] : -1;
28         return ri < rj;
29     }
30 }
31
32 void construct_sa(const string &S, int *sa) {
33       n = S.length();
34
35       for (int i = 0; i <= n; i++) {
36           sa[i] = i;
37           rank[i] = i < n ? S[i] : -1;
38      }
39
40      for (k = 1; k <= n; k *= 2) {
41           sort(sa, sa + n + 1, compare_sa);
42
43         tmp[sa[0]] = 0;
44         for (int i = 1; i <= n; i++) {
45               tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
46         }
47         for (int i = 0; i <= n; i++) rank[i] = tmp[i];
48     }
49 }
50
51 void construct_lcp(const string &S, int *sa, int *lcp) {
52     int n = S.length();
53     for (int i = 0; i <= n; i++) rank[sa[i]] = i;
54
55     int h = 0;
56     lcp[0] = 0;
57     for (int i = 0; i < n; i++) {
58           int j = sa[rank[i] - 1];
59
60         if (h > 0) h--;
61         for (; j + h < n && i + h < n; h++) if (S[i + h] != S[j + h]) break;
62
63         lcp[rank[i] - 1] = h;
64     }
65 }
66
67 string S, T;
68
69 void solve() {
70     int len1 = S.length();
71     S = S + ‘$‘ + T;
72
73     construct_sa(S, sa);
74     construct_lcp(S, sa, lcp);
75
76     int ans = 0;
77     for (unsigned i = 0; i < S.length(); i++) {
78           if ((sa[i] < len1) != (sa[i + 1] < len1))
79               ans = max(ans, lcp[i]);
80     }
81     cout << ans << endl;
82 }
83
84 int main(void) {
85     ios::sync_with_stdio(false);
86     while (cin >> S >> T) {
87           solve();
88     }
89     return 0;
90 }

Hdu 1403(后缀数组)

时间: 2024-07-29 06:45:47

Hdu 1403(后缀数组)的相关文章

HDU - 1403 后缀数组初步

题意:求两个串的最长公共子串 两个串连接起来然后求高度数组 注意两个sa值必须分别在不同一侧 本题是用来测试模板的,回想起青岛那次翻车感觉很糟糕 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #include<vec

hdu 3948 后缀数组

The Number of Palindromes Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2465    Accepted Submission(s): 841 Problem Description Now, you are given a string S. We want to know how many distin

hdu 3518 后缀数组

Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2906    Accepted Submission(s): 1201 Problem Description 035 now faced a tough problem,his english teacher gives him a string,whic

2017.3.4[hihocoder#1403]后缀数组一&#183;重复旋律

好久没发博了. 后缀数组板子题.具体实现就不解释了,hihocoder很良心. http://hihocoder.com/problemset/problem/1403 1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<vector> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostre

HDU - 3948 后缀数组+Manacher

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3948 题意:给定一个字符串,求字符串本质不同的回文子串个数. 思路:主要参考该篇解题报告 先按照manacher的构造方法改造一遍串,然后跑一遍manacher.求出以i为中心的最长回文串长度p[i]. 然后跑一遍后缀数组,若已经求得后缀sa[i-1]对答案的贡献,然后现在计算后缀sa[i],本来是要加上以sa[i]为中心的回文串的个数p[sa[i]]. 我们可以维护一个tmp,也就是上图中蓝色的框

HDU 6194 后缀数组

题意:求出现恰好 k次的子串(可以重叠)的个数: 分析: 刚开始想到了是后缀数组,但是有什么性质,具体怎么做的没有想到.回到主题来: 连续 k 次,说明这 k 个后缀排序后在一起,每次枚举 长度的为 k 的区间,用RMQ算出最长公共前缀长度,这里就有 len 个子串是 符合满足 k 次的,但是又有可能过短而不止出现了 k次,那么有多少呢? 那么就是 a 不属于,len - height[j+1],前面也一样.也就是每次只算他独有的子串,但是你可能问 len > k 的时候,可以从新组成一组子串!

HihoCoder - 1403 后缀数组一&#183;重复旋律

描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列. 小Hi在练习过很多曲子以后发现很多作品自身包含一样的旋律.旋律是一段连续的数列,相似的旋律在原数列可重叠.比如在1 2 3 2 3 2 1 中 2 3 2 出现了两次. 小Hi想知道一段旋律中出现次数至少为K次的旋律最长是多少? 输入 第一行两个整数 N和K.1≤N≤20000 1≤K≤N 接下来有 N 个整数,表示每个音的数字.1≤数字≤100 输出 一行一个整数,表示答案. Sample I

hihoCoder 后缀数组 重复旋律

#1403 : 后缀数组一·重复旋律 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列. 小Hi在练习过很多曲子以后发现很多作品自身包含一样的旋律.旋律是一段连续的数列,相似的旋律在原数列可重叠.比如在1 2 3 2 3 2 1 中 2 3 2 出现了两次. 小Hi想知道一段旋律中出现次数至少为K次的旋律最长是多少? 解题方法提示 输入 第一行两个整数 N和K.1≤N≤2000

「kuangbin带你飞」专题十八 后缀数组

layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kuangbin - 字符串 - 后缀数组 传送门 倍增法 struct DA{ bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } int t1[maxn],t2[maxn],c[maxn]; int r