“华为杯”杭州电子科技大学2023新生编程大赛 完美子串

“华为杯”杭州电子科技大学2023新生编程大赛 完美子串_第1张图片

 

#define ll long long//__int128 2^127-1(GCC)
#define PII pair
const int inf = 0x3f3f3f3f3f3f3f3f, N = 2e5 + 5, mod = 998244353;
char c[N], s[N * 2];
int cnt, mr, mid;
int p[N * 2 + 10];
signed main()
{
    ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        cnt = 0, mr = 0, mid = 0;
        string c;
        cin >> c;
        int n = c.length();
        c = ' ' + c;
        s[++cnt] = '~', s[++cnt] = '#';
        for (int i = 1; i <= n; i++)
        {
            s[++cnt] = c[i], s[++cnt] = '#';
        }
        s[++cnt] = '!';//形如“ ~#a#b#b#a#!”
        for (int i = 2; i <= cnt - 1; i++) {
            if (i < mr) p[i] = min(p[mid * 2 - i], mr - i + 1);
            else p[i] = 1;
            while (s[i - p[i]] == s[i + p[i]]) ++p[i];
            if (i + p[i] > mr) mr = i + p[i] - 1, mid = i;
        }//马拉车算法
        vectorwc;
        for (int i = 2 + 2; i <= cnt - 1 - 2; i+=2)
        {
            wc.push_back({ p[i],i });
        }//把从第4个开始的'#'的位置以及所能匹配最远的个数记录下来
        sort(wc.begin(), wc.end(), greater());//以匹配个数从大到小排序
        setse;//一次插入set中
        int maxx = 0;//记录结果
        for (int i = 0; i < wc.size(); i++)
        {
            int val = wc[i].first, pos = wc[i].second;
            int l = pos - val + 1, r = pos + val - 1;
            auto w1 = se.lower_bound(l); 
            if (w1 == se.end() || *w1 > pos) {

            }
            else {//因为时从大到小插入,所以如果能匹配到的话就更新
                maxx = max(maxx, (pos - *w1) / 2 * 3);
            }
            auto w2 = se.upper_bound(r);
            if (w2 == se.begin()) goto z;
            w2=prev(w2);
            if ( *w2 < pos) {

            }
            else {//同上
                maxx = max(maxx, (*w2 - pos) / 2 * 3);
            }
        z:;
            se.insert(pos);
        }
        cout << maxx << "\n";
    }
}

 

你可能感兴趣的:(华为)