Problem 4. Stringonomics 2018 Goldman Sachs Women's CodeSprint

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yixin94/article/details/83001532

题意:输入字符串S和P,给定Q个queries,每个query操作将S[x]变成c,c也可能和原先的S[x]相同。保证每个位置x只改变一次,而且P不再是S的子串之后不会再重复出现,问对少个query之后P不会再出现S中。

P是从出现到消失,正解是KMP+二分,二分每个mid处判断P是否是S的子串。但是我用O(QN)加上优化竟然也过了。。

KMP一次比较后可以得出P在S中出现的所有位置(最末端匹配处),每个query可能把原先不等于P的A[i,...,j]变成等于P,也可能把原先等于P的子串A[i,...,j]变成不等于P,或者没有影响。

所以不必在每个query都用KMP重新比较,可以维护一个set appear记录P和S match的位置index(match的终点)。

对于query x,P的长度为len,x影响的A中子串以x,x+1,...,x+len-1结尾的子串,所以可以用二分查找找到appear中在此范围内的index,再逐个移除。

如果移除之后appear为空,再用KMP更新匹配结果。

#include <bits/stdc++.h>

using namespace std;

string ltrim(const string &);
string rtrim(const string &);
vector<string> split(const string &);

set<int>appear;//q appear in p, the last matching index

void generateNext(vector<int> &nextArray, string needle) {
    nextArray[0] = -1;
    int k=-1, q;
    for (q = 1; q < needle.length(); ++q) {
        while (k>=0 && needle[k+1]!=needle[q])
            k = nextArray[k];
        if (needle[k+1] == needle[q])
            k++;
        nextArray[q] = k;
    }
    // for (int i = 0; i < needle.length(); ++i) {
    //     cout << nextArray[i] << endl;
    // }
}
int match(string hayStack, string needle, vector<int>& nextArray) {
//    cout<<"in match "<<hayStack<<" "<<needle<<endl;
    if (hayStack.length() < needle.length()) return 0;
    if (hayStack.length() == needle.length()) {
        if (hayStack == needle)
        {
            appear.insert(hayStack.length()-1);
            return 1;
        }
        return 0;
    }
    int q=-1, i=0;
    int cnt=0;
    for (i = 0; i < hayStack.length(); ++i) {
        while (q>=0 && needle[q+1]!=hayStack[i])
            q = nextArray[q];
        if (needle[q+1] == hayStack[i])
            q++;
        if (q == needle.length()-1) {
            cnt++;
//            cout<<"appear at "<<i<<endl;
            appear.insert(i);
            q = nextArray[q];
        }
    }
    return cnt;
}

int main()
{
    string t_temp;
    getline(cin, t_temp);

    int t = stoi(ltrim(rtrim(t_temp)));

    for (int t_itr = 0; t_itr < t; t_itr++) {
        string s;
        getline(cin, s);

        string p;
        getline(cin, p);

        string q_temp;
        getline(cin, q_temp);

        int q = stoi(ltrim(rtrim(q_temp)));
        vector<int> nextArray(p.length(),0);
        generateNext(nextArray,p);
        appear.clear();
        int ans=0;
        bool flg=false;
        int cnt=match(s,p,nextArray);
//        cout<<"start"<<endl;
        if(cnt==0)
        {
            flg=true;
//            cout<<"Case #"<<ca<<": "<<ans<<endl;
            cout<<ans<<endl;
//            continue;
        }
        for (int q_itr = 0; q_itr < q; q_itr++) {
            string first_multiple_input_temp;
            getline(cin, first_multiple_input_temp);

            vector<string> first_multiple_input = split(rtrim(first_multiple_input_temp));

            int x = stoi(first_multiple_input[0]);

            char c = first_multiple_input[1][0];
            char prec=s[x];
            s[x]=c;
            ans++;
            if(flg==true)
            {
                continue;
            }
            if(c==prec)
            {
                continue;
            }
            else
            {
//                cout<<"here0"<<endl;
                int left=x;
                int right=x+p.length()-1;
//                cout<<"left "<<left<<" right "<<right<<endl;
                set<int>::iterator lower=appear.lower_bound(left);
                set<int>::iterator upper=appear.upper_bound(right);

                if(lower==appear.end())
                {
                    continue;
                }
                else
                {
                    appear.erase(lower,upper);
                    if(appear.size()==0)
                    {
//                        cout<<"re cmp afer erase at here1"<<endl;
                        int cnt=match(s,p,nextArray);
                        if(cnt==0)
                        {
                            flg=true;
//                            cout<<"Case #"<<ca<<": "<<ans<<endl;
                            cout<<ans<<endl;
                        }
                    }
                }
            }
        }
        if(flg==false)
        {
//            cout<<"Case #"<<ca<<": "<<"-1"<<endl;
            cout<<"-1"<<endl;
        }
    }

    return 0;
}

string ltrim(const string &str) {
    string s(str);

    s.erase(
        s.begin(),
        find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace)))
    );

    return s;
}

string rtrim(const string &str) {
    string s(str);

    s.erase(
        find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(),
        s.end()
    );

    return s;
}

vector<string> split(const string &str) {
    vector<string> tokens;

    string::size_type start = 0;
    string::size_type end = 0;

    while ((end = str.find(" ", start)) != string::npos) {
        tokens.push_back(str.substr(start, end - start));

        start = end + 1;
    }

    tokens.push_back(str.substr(start));

    return tokens;
}

猜你喜欢

转载自blog.csdn.net/yixin94/article/details/83001532