• 【hdu 1403】Longest Common Substring


    【链接】h在这里写链接


    【题意】


    求两个串的最长公共子串

    【题解】


    Sa[i]表示的是字典序为i的后缀的起始位置。
    可以把两个字符串合在一起(中间用一个比'z'大的字符分割);
    则如果Sa[i-1]<len1且Sa[i]>len1;
    则它们表示s1和s2的两个后缀。
    取height[i]然后求最大值就可以了。
    (height[i]表示的是字典序为i-1和字典序为i的后缀它们的最长公共前缀)
    在这里,也即两个子串了。

    【错的次数】


    5+

    【反思】


    桶的大小得设置成2e5才行。。不是字符ascill码的最大值。。

    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5;
    const int MAX_CHAR = 255;//每个数字的最大值。
    char s[N + 10];//如果是数字,就写成int s[N+10]就好,从0开始存
    int Sa[N + 10], T1[N + 10], T2[N + 10], C[N+10];
    //Rank数组下标是从0开始的,表示的是从i开始的后缀的排名
    //Sa数组又是从1开始的,表示的是第i名的(i>=1)后缀是从字符串中的第几个字符开始的.
    int Height[N + 10], Rank[N + 10];
    
    void build_Sa(int n, int m) {
    	int i, *x = T1, *y = T2;
    	for (i = 0; i<m; i++) C[i] = 0;
    	for (i = 0; i<n; i++) C[x[i] = s[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 (int k = 1; k <= n; k <<= 1)
    	{
    		int p = 0;
    		for (i = n - k; i<n; i++) y[p++] = i;
    		for (i = 0; i<n; i++) if (Sa[i] >= k) y[p++] = Sa[i] - k;
    		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]] = y[Sa[i - 1]] == y[Sa[i]] && y[Sa[i - 1] + k] == y[Sa[i] + k] ? p - 1 : p++;
    		if (p >= n) break;
    		m = p;
    	}
    }
    
    void getHeight(int n)
    {
    	int i, j, k = 0;
    	for (i = 1; i <= n; i++) Rank[Sa[i]] = i;
    	for (i = 0; i<n; i++) {
    		if (k) k--;
    		j = Sa[Rank[i] - 1];
    		while (s[i + k] == s[j + k]) k++;
    		Height[Rank[i]] = k;
    	}
    }
    
    int main() {
    	int i, n;
    	while (scanf("%s", s) != EOF) {
    		int len = strlen(s);
    		s[len] = (int)('z') + 1;
    		scanf("%s", s + len + 1);
    		n = strlen(s),s[n] = 0;
    		build_Sa(n + 1, MAX_CHAR);//注意调用n+1
    		getHeight(n);
    		int ma = 0;
    		for (i = 2; i <= n; i++)
    			if ((Sa[i - 1]<len && Sa[i]>len) || (Sa[i - 1] > len && Sa[i] < len))
    				ma = max(ma, Height[i]);
    		printf("%d\n", ma);
    	}
    	return 0;
    }


  • 相关阅读:
    小注意1
    javascript求相对路径
    js网页返回顶部和楼层跳跃的实现原理
    函数传值的学习笔记
    每日一题——归并排序
    python文件处理
    Docker数据卷
    Docker镜像原理
    Docker可视化之Portainer
    Docker部署Nginx、Tomcat
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626016.html
Copyright © 2020-2023  润新知