zoukankan      html  css  js  c++  java
  • 【hdu 6208】The Dominator of Strings

    【链接】h在这里写链接


    【题意】


    问你n个串里面有没有一个串,使得其余n-1个串都是他的子串。

    【题解】


    后缀数组.
    答案肯定是那个最长的串。
    则,把那个串求一下Sa数组(注意仅仅那个最长的串求)。
    然后枚举其余n-1个子串。
    看看它们是不是那个最长的串的子串;
    (可以用一个类似二分的东西判断它是不是子串。);
    (字符串比较,如果比当前后缀小,就往后缀小的地方,否则往大的地方,最后判断是不是子串。)
    ->利用Sa数组。
    时间复杂度为O(n*logn)的样子。
    感觉又解锁了新姿势。
    (这里可以不用获取Height函数了)


    【错的次数】


    0

    【反思】


    主串的长度没那么长的时候,用这种方法的确合适。
    hdu 2222那题。主串的长度太长了(1e6);
    就显得没那么优秀了。

    【代码】

    #include<bits/stdc++.h>  
    using namespace std;
    
    const int N = 1e5;
    const int SN = 2e2;
    const int MAX_CHAR = 300;//每个数字的最大值。  
    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, L[N + 10], R[N + 10];
    int Le[N + 10];
    vector <string> vec;
    bool flag[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;
        }
    }
    
    bool contain(string &S, string T) {//最长的那个串和 短串
        int l = 1, r = S.size(),temp = -1;
        while (l <= r) {
            int m = (l + r) >> 1;
            if (S.compare(Sa[m], T.length(), T) <= 0)//如果后缀比S来的小。
            {
                temp = m;
                l = m + 1;//可以再大一点
            }
            else
            {
                r = m - 1;
            }
        }
        if (temp == -1) 
            return 0;
        else
            return S.compare(Sa[temp], T.length(), T) == 0;
    }
    
    int main() {
        //freopen("F:\rush.txt", "r", stdin);
        ios::sync_with_stdio(0), cin.tie(0);
        int TT;
        cin >> TT;
        while (TT--) {
            int T;
            cin >> T;
            int n = 0, ma = 0, idxma;
            string ss;
            vec.clear();
            vec.push_back(" ");
            for (int i = 1; i <= T; i++) {
                cin >> ss;
                vec.push_back(ss);
                if ((int)ss.size() > ma) {
                    ma = (int)ss.size();
                    idxma = i;
                }
            }
            for (int i = 0; i <= (int) vec[idxma].size() - 1; i++)
                s[n++] = vec[idxma][i];
            s[n] = 0;
            build_Sa(n + 1, MAX_CHAR);//注意调用n+1  
            bool ok = true;
            for (int i = 1; i <= T; i++) 
                if (idxma!=i){//不能是最大的那个,那个是要被匹配的。
                    if (!contain(vec[idxma], vec[i])) {
                        ok = false;
                        break;
                    }
                }
            if (ok) {
                cout << vec[idxma] << endl;
            }
            else
                cout << "No" << endl;
        }
        return 0;
    }


  • 相关阅读:
    那么这几天都是自己和工作上的事情比较零零散散
    在大家都返现的时候却有人什么都不奉献
    今天觉得自己好像比较紧张
    今天是下午有雨
    今天是星期五,上班已经三个礼拜了
    今天晚上控制电脑前,要提前开机
    其实对于家里的电脑就是硬盘不太好
    家里主要忙着建立房子
    今天装了一个RTI工具
    昨天已经开始讲业务的部分
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626000.html
Copyright © 2011-2022 走看看