Gym - 101164K Cutting 哈希+枚举

ACM-ICPC Southeastern European Regional Programming Contest
Bucharest, Romania – Vinnytsya, Ukraine
October 22, 2016


Problem K Cutting

Input File: K.in
Output File: standard output
Time Limit: 0.2 seconds (C/C++)
Memory Limit: 256 megabytes


You have two strings and you need to check whether you can cut the second one into three
pieces so that the first string can be concatenated from these three pieces.


Input

The input file contains two non-empty strings, each on a separate line. Each string consists of at
most 5000 lowercase roman letters. Strings have the same length and each letter has the same
number of occurrences in both strings.


Output

Print YES if it is possible to cut the string as described, and NO in the opposite case. If you print
YES, the following three lines should contain the parts of the second string in the correct
concatenation order. These parts cannot be empty. If you have several options to cut, print any of
them.


Sample input     Sample output

Beast                                                YES
betas                                                 be
                                                           as
                                                           t

----------------------------------------------------------------

Royalitem                                         NO
Romeitaly

----------------------------------------------------------------


Source

Southeastern European Regional Programming Contest
Bucharest, Romania – Vinnytsya, Ukraine

Gym - 101164K


My Solution

题意:给出字符串A和B,字符串A大小写不区分,字符串B由小写字母构成,构成AB的每种字母的个数相同,询问是否能把B切成3份,重构出字符串A,如果能则输出那三份子串,并按照A的顺序输出。


哈希+枚举

刚开始的时候,以为可以用KMP来过,白白TLE了2发才明白,自己走远了,这题是合适的做法是hash。

O(n^2)的枚举字符串B 的0~i-1 为第一段,i~j-1 为第二段,j~n-1为第三锻,

然后每次借用这三段的哈希值去和A串匹配,这三段有A(3,3) == 6种排列方式,所以枚举这6种排列,

之后借用它们的哈希值判断能否构造出字符串A。

复杂度 O(n^2)


#include 
#include 
#include 
using namespace std;
typedef unsigned long long ull;
const int MAXN = 5e3 + 8;
const ull p = 1e12 + 7;             //!

string pa, t;

struct HASH{
    ull Hash[MAXN], xp[MAXN];
    void init1(int sz){
        xp[0] = 1;
        for(int i = 1; i <= sz; i++) xp[i] = xp[i-1] * p;
    }
    void init2(const string &s){//0~n-1 based
        int sz = s.size();
        Hash[sz] = 0;
        for(int i = sz - 1; i >= 0; i--){
            Hash[i] = Hash[i+1] * p + (s[i] - 'a' + 1);
        }
    }
    ull get_Hash(const int& st, const int& len){
        return Hash[st] - Hash[st + len] * xp[len];
    }

} hashp, hasht;
int main()
{
    #ifdef LOCAL
    freopen("k.txt", "r", stdin);
    //freopen("k.out", "w", stdout);
    int T = 5;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);


    cin >> pa >> t;
    int n = pa.size(), i, j, sz = 0, ans1 = -1, ans1len, ans2 = -1, ans2len, ans3 = -1, ans3len;
    for(i = 0; i < n; i++){
        if(pa[i] >= 'A' && pa[i] <= 'Z'){
            pa[i] = pa[i] - 'A' + 'a';
        }
    }
    hashp.init1(n);
    hashp.init2(pa);
    hasht.init1(n);
    hasht.init2(t);
    for(i = 1; i < n - 1; i++){
        if(ans1 != -1) break;
        for(j = i + 1; j < n; j++){
            if(ans1 != -1) break;
            //1
            if(hasht.get_Hash(0, i) == hashp.get_Hash(0, i)){
                if(hasht.get_Hash(i, j - i) == hashp.get_Hash(i, j - i)){
                    if(hasht.get_Hash(j, n - j) == hashp.get_Hash(j, n - j)){
                        ans1 = 0, ans1len = i;
                        ans2 = i, ans2len = j - i;
                        ans3 = j, ans3len = n - j;
                    }
                }
                if(hasht.get_Hash(i, j - i) == hashp.get_Hash(n - (j - i), j - i)){
                    if(hasht.get_Hash(j, n - j) == hashp.get_Hash(i, n - j)){
                        ans1 = 0, ans1len = i;
                        ans2 = j, ans2len = n - j;
                        ans3 = i, ans3len = j - i;
                    }
                }
            }
            //2
            if(hasht.get_Hash(0, i) == hashp.get_Hash(n - i, i)){
                if(hasht.get_Hash(i, j - i) == hashp.get_Hash(0, j - i)){
                    if(hasht.get_Hash(j, n - j) == hashp.get_Hash(j - i, n - j)){
                        ans1 = i, ans1len = j - i;
                        ans2 = j, ans2len = n - j;
                        ans3 = 0, ans3len = i;
                    }
                }
                if(hasht.get_Hash(i, j - i) == hashp.get_Hash(n - j, j - i)){
                    if(hasht.get_Hash(j, n - j) == hashp.get_Hash(0, n - j)){
                        ans1 = j, ans1len = n - j;
                        ans2 = i, ans2len = j - i;
                        ans3 = 0, ans3len = i;
                    }
                }
            }
            //3.1
            if(hasht.get_Hash(0, i) == hashp.get_Hash(j - i, i)){
                if(hasht.get_Hash(i, j - i) == hashp.get_Hash(0, j - i)){
                    if(hasht.get_Hash(j, n - j) == hashp.get_Hash(j, n - j)){
                        ans1 = i, ans1len = j - i;
                        ans2 = 0, ans2len = i;
                        ans3 = j, ans3len = n - j;
                    }
                }
            }
            //3.2
            if(hasht.get_Hash(0, i) == hashp.get_Hash(n - j, i)){
                if(hasht.get_Hash(i, j - i) == hashp.get_Hash(n - (j - i), j - i)){
                    if(hasht.get_Hash(j, n - j) == hashp.get_Hash(0, n - j)){
                        ans1 = j, ans1len = n - j;
                        ans2 = 0, ans2len = i;
                        ans3 = i, ans3len = j - i;
                    }
                }
            }

        }
    }


    if(ans1 == -1) cout << "NO" << endl;
    else{
        cout << "YES\n" << t.substr(ans1, ans1len) << "\n" << t.substr(ans2, ans2len) << "\n" << t.substr(ans3, ans3len) << endl;
    }



    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}



  Thank you!

                                                                                                                                             ------from ProLights

你可能感兴趣的:(☺藏题阁☺,字符串:hash,Gym,算法的艺术)