zoukankan      html  css  js  c++  java
  • 【hdu 2328】Corporate Identity

    【链接】h在这里写链接


    【题意】


    找一个字典序最小的公共最长子串;

    【题解】


    后缀数组。
    把所有的串用不同的分隔符分开。(大于'z'的分隔符);
    然后求出那几个固定的数组。
    二分一下那个子串的长度.
    看看是不是在N个串里面都有这个串即可。
    可以用一个下标,来记录某个位置开始的后缀是第几个串里面的(即输入的N个串里面的哪一个串).
    子串长度越大显然越不可能存在。
    (因子本来就是按照后缀排的。所以找到的第一个符合要求的子串肯定是字典序最小的)

    【错的次数】


    0

    【反思】


    一开始记录答案的时候,记录错了,应该记录的是Sa[i]而不是i...
    因为i是排名啊。。Sa[i]才是这个排名的后缀的起点。

    【代码】

    /*
    N*logn复杂求出Rank数组以及Sa数组
    Rank数组下标是从0开始的,表示的是从i开始的后缀的排名(排名>=1).
    Sa数组又是从1开始的,表示的是第i名的(i>=1)后缀是从字符串中的第几个字符开始的(字符位置>=0).
    Height[i]从1开始,表示的是字典序为i和字典序为i-1的后缀的最长公共前缀。
    */
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 8e5 + 6000;
    const int SN = 2e2;
    const int MAX_CHAR = 4500;//每个数字的最大值。
    int s[N + 10];//如果是数字,就写成int s[N+10]就好,从0开始存
    int Sa[N + 10], T1[N + 10], T2[N + 10], C[N + 10], T;
    int Height[N + 10], Rank[N + 10], idx[N + 10], in[N + 10], tag;
    char str[SN + 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;
    	}
    }
    
    void check(int pos, int i, int &num) {
    	if (in[idx[Sa[pos]]] != i) {
    		num++;
    		in[idx[Sa[pos]]] = i;
    	}
    }
    
    bool ok(int len, int n) {
    	for (int i = 1; i <= T; i++) in[i] = 0;
    	for (int i = 2; i <= n; i++)
    		if (Height[i] >= len) {
    			int j = i, num = 1;
    			in[idx[Sa[i - 1]]] = i;
    			check(i, i, num);
    			while (j + 1 <= n && Height[j + 1] >= len) {
    				j++;
    				check(j, i, num);
    			}
    			if (num == T) {
    				tag = Sa[i - 1];
    				return true;
    			}
    			i = j;
    		}
    	return false;
    }
    
    int main() {
    	//freopen("F:\\rush.txt", "r", stdin);
    	ios::sync_with_stdio(0), cin.tie(0);
    	while (cin >> T && T) {
    		int n = 0;
    		for (int i = 1; i <= T; i++) {
    			cin >> str;
    			for (int j = 0; j < (int)strlen(str); j++) {
    				idx[n] = i;
    				s[n++] = str[j];
    			}
    			s[n++] = 300 + i;
    		}
    		s[n] = 0;
    		build_Sa(n + 1, MAX_CHAR);//注意调用n+1
    		getHeight(n);
    		int l = 1, r = 200, temp = 0;
    		while (l <= r) {
    			int m = (l + r) >> 1;
    			if (ok(m, n)) {
    				temp = m;
    				l = m + 1;
    			}
    			else
    				r = m - 1;
    		}
    		if (temp == 0) {
    			cout << "IDENTITY LOST" << endl;
    		}
    		else {
    			for (int i = tag; i <= tag + temp - 1; i++)
    				cout << char(s[i]);
    			cout << endl;
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    《DSP using MATLAB》Problem 6.17
    一些老物件
    《DSP using MATLAB》Problem 6.16
    《DSP using MATLAB》Problem 6.15
    《DSP using MATLAB》Problem 6.14
    《DSP using MATLAB》Problem 6.13
    《DSP using MATLAB》Problem 6.12
    《DSP using MATLAB》Problem 6.11
    P1414 又是毕业季II
    Trie树
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626013.html
Copyright © 2011-2022 走看看