字符串处理之后缀数组

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 #define min(x,y) x>y? y:x
 6 #define N 200010
 7 int dp[N][33];
 8 int wa[N], wb[N], wsf[N], wv[N], sa[N];
 9 int ra[N], height[N], s[N];
10 char str[N], str1[N];
11 int cmp(int *r, int a, int b, int k)
12 {
13     return r[a] == r[b] && r[a + k] == r[b + k];
14 }
15 void getsa(int *r, int *sa, int n, int m)
16 {
17     int i, j, p, *x = wa, *y = wb, *t;
18     for (i = 0; i < m; i++)  wsf[i] = 0;
19     for (i = 0; i < n; i++)  wsf[x[i] = r[i]]++;
20     for (i = 1; i < m; i++)  wsf[i] += wsf[i - 1];
21     for (i = n - 1; i >= 0; i--)  sa[--wsf[x[i]]] = i;
22     p = 1;
23     j = 1;
24     for (; p < n; j *= 2, m = p)
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++)  wsf[i] = 0;
30         for (i = 0; i < n; i++)  wsf[wv[i]]++;
31         for (i = 1; i < m; i++)  wsf[i] += wsf[i - 1];
32         for (i = n - 1; i >= 0; i--)  sa[--wsf[wv[i]]] = y[i];
33         t = x;
34         x = y;
35         y = t;
36         x[sa[0]] = 0;
37         for (p = 1, i = 1; i < n; i++)
38             x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
39     }
40 }
41 void getheight(int *r, int n)
42 {
43     int i, j, k = 0;
44     for (i = 1; i <= n; i++)  ra[sa[i]] = i;
45     for (i = 0; i < n; i++)
46     {
47         if (k)
48             k--;
49         else
50             k = 0;
51         j = sa[ra[i] - 1];
52         while (r[i + k] == r[j + k])
53             k++;
54         height[ra[i]] = k;
55     }
56 }
57 int main()
58 {
59     while (cin >> str)
60     {
61         cin >> str1;
62         int n = 0, len = strlen(str);
63         for (int i = 0; i < len; i++)
64             s[n++] = str[i] - ‘a‘ + 1;
65         s[n++] = 28;
66         len = strlen(str1);
67         for (int i = 0; i < len; i++)
68             s[n++] = str1[i] - ‘a‘ + 1;
69         s[n] = 0;
70         getsa(s, sa, n + 1, 30);
71         getheight(s, n);
72         int max = 0, pos = 0;
73         len = strlen(str);
74         for (int i = 2; i<n; i++)
75         if (height[i]>max)
76         {
77             if (0 <= sa[i - 1] && sa[i - 1] < len&&len < sa[i])
78                 max = height[i];
79             if (0 <= sa[i] && sa[i] < len&&len < sa[i - 1])
80                 max = height[i];
81         }
82         cout << max << endl;
83     }
84     return 0;
85 }

时间: 2024-10-09 22:39:26

字符串处理之后缀数组的相关文章

poj 2774 最长公共子串--字符串hash或者后缀数组或者后缀自动机

http://poj.org/problem?id=2774 想用后缀数组的看这里:http://blog.csdn.net/u011026968/article/details/22801015 本文主要讲下怎么hash去找 开始的时候写的是O(n^2 logn)算法 果断超时...虽然也用了二分的,, 代码如下: //hash+二分 #include <cstdio> #include <cstring> #include <algorithm> #include

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树)

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树) 题面 给出一个长度为\(n\)的字符串\(s\),以及\(m\)组询问.每个询问是一个四元组\((a,b,c,d)\),问\(s[a,b]\)的所有子串和字符串\(s[c,d]\)的最长公共前缀长度的最大值. \(n,m \leq 10^5\) 分析 显然答案有单调性.首先我们二分答案\(mid\),考虑如何判定. 如果mid这个答案可行,那么一定存在一个后缀x,它的开头在\([a,

BZOJ_1031_[JSOI2007]_字符串加密_(后缀数组)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1031 长度为n的字符串形成环,枚举开头位置,得到n个长度为n的串,将这些串排序,然后按照顺序输出每一个串的最后一个字符. 分析 将原串复制一遍接在自己的后面,这样n个串都在总串里面出现了. 对于这n个串中的两个a,b,如果a<b,那么以a开头的后缀就<以b开头的后缀. 所以我们求一下后缀数组就好了. 1 #include <bits/stdc++.h> 2 using name

[BZOJ4556][TJOI2016&amp;&amp;HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1360  Solved: 545[Submit][Status][Discuss] Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE O,嫁给高富帅,走上人生巅

cf244D. Match &amp; Catch 字符串hash (模板)或 后缀数组。。。

D. Match & Catch 可以用各种方法做,字符串hash,后缀数组,dp,拓展kmp,字典树... 字符串hash(模板) http://blog.csdn.net/gdujian0119/article/details/6777239 BKDR Hash Function : // BKDR Hash Function unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 13

cf244D. Match &amp;amp; Catch 字符串hash (模板)或 后缀数组。。。

D. Match & Catch 能够用各种方法做.字符串hash.后缀数组,dp.拓展kmp,字典树.. . 字符串hash(模板) http://blog.csdn.net/gdujian0119/article/details/6777239 BKDR Hash Function : // BKDR Hash Function unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 1

后缀数组(一堆干货)

其实就是将两篇论文里的东西整合在了一起,并且提供了一个比较好理解的板. 后缀数组 字符串:一个字符串S是将n个字符顺次排列形成的数组,n称为S的长度,表示为len(S).S的第i个字符表示为S[i]. 子串:字符串S的子串S[i…j],i<=j,表示从S串中从i到j这一段,也就是顺次排列S[i],S[i+1],……,S[j]形成的字符串. 后缀:后缀是指从某个位置i开始到整个字符串末尾结束的一个特殊子串.字符串S的从i开关的后缀表示为Suffix(S,i),也就是Suffix(S,i)=S[i…

hdu1403(后缀数组模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1403 题意: 给出两个字符串, 求他们的最长公共子串 思路: 两个字符串的最长公共子串长度显然就是两个字符串的所有后缀中的最长公共前缀长度. 可以先用一个没有出现的字符(便于后面区分后缀是否属于相同字符串)将两个字符串连成一个字符串,再用后缀数组求其height, SA数组, 对于当前 i, 通过 SA 数组区分后缀 i 和 i - 1 是否在同一个初始字符串中, 若不是则用 height[i] 维

hdu5442(2015长春赛区网络赛1006)后缀数组+KMP /最小表示法?

题意:给定一个由小写字母组成的长度为 n 的字符串,首尾相连,可以从任意一个字符开始,顺时针或逆时针取这个串(长度为 n),求一个字典序最大的字符串的开始字符位置和顺时针或逆时针.如果有多个字典序最大的字符串,优先选择开始位置靠前的,如果开始位置相同,优先选择顺时针. 这种字符串的问题,第一反应是后缀数组,为了达到首尾相连的目的,所以先复制了一个两倍长的该字符串,然后再将串倒置,也弄成两倍长度,得到顺逆时针的两倍长的串,并对这两个字符串分别做后缀数组,得到 sa 数组(该串字典序第几小的后缀的开