zoukankan      html  css  js  c++  java
  • [POJ 2774]Long Long Message

    题目链接

    题目大意 : 给你两个字符串,求出他们最长公共子串的长度。

    首先把两个字符串连起来,中间加一个不会出现的字符,如%,防止找lcp的时候前面的找到后面去。

    然后我们发现答案是这个心字符串的任意两个子串lcp的最大值。然后会发现这个最大值只可能出现在 (sa[i], sa[i - 1]) 这里,因为排名差的更远肯定差别更大。

    所以求出height,然后取 (sa[i], sa[i - 1]) 分别在两个原串的 (height[i]) 最大值即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<vector>
    #include<cmath>
    
    using namespace std;
    
    #define N 300005
    
    string a, b, s;
    
    int n, m, sa[N], rk[N], height[N], x[N], y[N], c[N];
    
    void Get_Sa()
    {
    	for(int i = 1; i <= n; i++) c[x[i] = s[i]]++;
    	for(int i = 2; i <= m; i++) c[i] += c[i - 1];
    	for(int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
    	for(int k = 1; k <= n; k <<= 1)
    	{
    		int num = 0;
    		for(int i = n - k + 1; i <= n; i++) y[++num] = i;
    		for(int i = 1; i <= n; i++) if(sa[i] > k) y[++num] = sa[i] - k;
    		for(int i = 1; i <= m; i++) c[i] = 0;
    		for(int i = 1; i <= n; i++) c[x[i]]++;
    		for(int i = 2; i <= m; i++) c[i] += c[i - 1];
    		for(int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;
    		std::swap(x, y);
    		num = 1, x[sa[1]] = 1;
    		for(int i = 2; i <= n; i++)
    			x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num;
    		if(num == n) break;
    		m = num;
    	}
    }
    
    void Get_height()
    {
    	for(int i = 1; i <= n; i++) rk[sa[i]] = i;
    	int k = 0;
    	for(int i = 1; i <= n; i++)
    	{
    		if(rk[i] == 1) continue;
    		if(k) k--;
    		int j = sa[rk[i] - 1];
    		while(i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
    		height[rk[i]] = k;
    	}
    }
    
    int main()
    {
    	cin >> a >> b;
    	int la = a.size();
    	s = ' ' + a + '%' + b;
    	n = s.size() - 1, m = 122;
    	Get_Sa();
    	Get_height();
    	int ans = 0;
    	for(int i = 2; i <= n; i++)
    	{
    		int x = sa[i - 1], y = sa[i];
    		if((x <= la && y > la + 1) || (x > la + 1 && y <= la)) ans = max(ans, height[i]);
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    010-你觉得单元测试可行吗
    跳台阶
    斐波那契数列
    旋转数组的最小数字
    用两个栈实现队列
    重建二叉树
    从尾到头打印链表
    替换空格
    二维数组中的查找
    Best Time to Buy and Sell Stock III
  • 原文地址:https://www.cnblogs.com/LJB00131/p/12585431.html
Copyright © 2011-2022 走看看