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;
    }


  • 相关阅读:
    .NET实现Excel文件的读写 未测试
    权限管理设计
    struts1中配置应用
    POJ 2139 Six Degrees of Cowvin Bacon(floyd)
    POJ 1751 Highways
    POJ 1698 Alice's Chance
    POJ 1018 Communication System
    POJ 1050 To the Max
    POJ 1002 4873279
    POJ 3084 Panic Room
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626000.html
Copyright © 2011-2022 走看看