hihocoder-1415 后缀数组三·重复旋律3 两个字符串的最长公共子串
Posted Luke_Ye
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder-1415 后缀数组三·重复旋律3 两个字符串的最长公共子串相关的知识,希望对你有一定的参考价值。
把s1,s2拼接,求Height。相邻的Height判断左右串起点是否在两个串中,另外对Height和s1.length()-SA[i-1]取min。
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #include <iomanip> #include <stdlib.h> #include <time.h> #define LL long long using namespace std; const LL mod = 100001; const LL N = 300010; int s1l, s2l; class SF { //N:数组大小 public: int x[N], y[N], c[N]; int Height[N],str[N], SA[N], Rank[N];//Height数组从2开始 int slen; int m=1050;//字符集处理大小(传入如果不是数字,需要做位移转换) bool cmp(int* r, int a, int b, int l) { return r[a] == r[b] && r[a + l] == r[b + l]; } void Suffix(int n) { ++n; int i, j, p; for (i = 0; i < m; ++i) c[i] = 0; for (i = 0; i < n; ++i) c[x[i] = str[i]]++; for (i = 1; i < m; ++i) c[i] += c[i - 1]; for (i = n - 1; i >= 0; --i) SA[--c[x[i]]] = i; for (j = 1; j <= n; j <<= 1) { p = 0; for (i = n - j; i < n; ++i) y[p++] = i; for (i = 0; i < n; ++i) if (SA[i] >= j) y[p++] = SA[i] - j; for (i = 0; i < m; ++i) c[i] = 0; for (i = 0; i < n; ++i) c[x[y[i]]]++; for (i = 1; i < m; ++i) c[i] += c[i - 1]; for (i = n - 1; i >= 0; --i) SA[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[SA[0]] = 0; for (i = 1; i < n; ++i) { x[SA[i]] = cmp(y, SA[i - 1], SA[i], j) ? p - 1 : p++; } if (p >= n)break; m = p; } int k = 0; n--; for (i = 0; i <= n; ++i) Rank[SA[i]] = i; for (i = 0; i < n; ++i) { if (k)--k; j = SA[Rank[i] - 1]; while (str[i + k] == str[j + k])++k; Height[Rank[i]] = k; //cout << k << endl; } } void init(string s)//不论什么参数,用引用传入 { slen = s.length(); for (int i = 0; i < slen; i++) str[i] =s[i]-‘a‘+2;//如果是字符,映射成从1开始的序列 str[slen] = 1;//0作为结束符,防止越界 Suffix(slen); } LL solve() { int ans = 0; for (int i = 2; i <= slen; i++) { int sa1 = SA[i - 1],sa2=SA[i]; if (sa1 > sa2) swap(sa1, sa2); if (sa1 >= s1l || sa2 < s1l) continue; ans = max(ans, min(s1l - sa1, Height[i])); } return ans; } }sf; LL dp[35][2]; LL n; int main() { cin.sync_with_stdio(false); string s1,s2; while (cin >> s1>>s2) { s1l = s1.length(); s2l = s2.length(); sf.init(s1+s2); cout << sf.solve() << endl; } return 0; }
以上是关于hihocoder-1415 后缀数组三·重复旋律3 两个字符串的最长公共子串的主要内容,如果未能解决你的问题,请参考以下文章
HiHocoder1415 : 后缀数组三·重复旋律3 & Poj2774:Long Long Message