牛客网暑期ACM多校训练营(第九场)F.Typing practice

题目描述 

Niuniu is practicing typing.

Given n words, Niuniu want to input one of these. He wants to input (at the end) as few characters (without backspace) as possible,

to make at least one of the n words appears (as a suffix) in the text.

Given an operation sequence, Niuniu want to know the answer after every operation.

An operation might input a character or delete the last character.

输入描述:

The first line contains one integer n.
In the following n lines, each line contains a word.
The last line contains the operation sequence.
'-' means backspace, and will delete the last character he typed.

He may backspace when there is no characters left, and nothing will happen.

1 <= n <= 4
The total length of n words <= 100000

The length of the operation sequence <= 100000

The words and the sequence only contains lower case letter.

输出描述:

You should output L +1 integers, where L is the length of the operation sequence.

The i-th(index from 0) is the minimum characters to achieve the goal, after the first i operations.

示例1

输入

复制

2
a
bab
baa-

输出

复制

1
1
0
0
0

说明

"" he need input "a" to achieve the goal.
"b" he need input "a" to achieve the goal.
"ba" he need input nothing to achieve the goal.
"baa" he need input nothing to achieve the goal.
"ba" he need input nothing to achieve the goal.

示例2

输入

复制

1
abc
abcd

输出

复制

3
2
1
0
3

说明

suffix not substring.

思路:一共只有四个单词,用KMP对每个单词求出next数组,每当操作串增加一个字母时,就把字母看作添加在了单词的后面,只需要向后多计算一位next值即可,len-next[len]就是要添加的字符串长度,找最小值即可。

因为循环节的存在会将KMP算法复杂度卡的很高,比赛中T到怀疑人生。使用优化的next_val数组作为跳转表即可。

给一组极端的数据:

单词:aaaaaaaaaa......aaaa

文本:b-b-b-b-b-.......b-b-b-b-

因为前面全是循环节,每次求b的next值都是O(N),一共要求N/2次,一般的kmp会被卡成N^2。

参考https://blog.csdn.net/hcx11333/article/details/81781081


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <cstdlib>
#include <set>
#include <string>
#include <time.h>

using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;

char str[4][maxn], des[maxn];
int nxt[4][maxn], hi[maxn], ans[maxn], val[4][maxn];
int len[4];

void get_next(char s[], int nxt[], int val[], int len) {
    int i = 0,j = -1;
    nxt[0] = -1;
    val[0] = -1;
    while(i < len) {
        if(j == -1 || s[i] == s[j]) {
            // 计算当前位val值
            if (j == -1) {
                val[i] = (s[i] == s[0] ? -1 : nxt[i]);
            } else {
                val[i] = (s[i] == s[nxt[i]] ? val[nxt[i]] : nxt[i]);
            }
            // 当前位的nxt值,存在后一位中
            ++i;
            ++j;
            nxt[i] = j;
        } else {
            j = val[j];
        }
    }
}

int main(){
    int n, l, mn = inf;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%s", str[i]);
        len[i] = strlen(str[i]);
        mn = min(mn, len[i]);
        str[i][len[i]] = '0' + i;
        ++len[i];
        get_next(str[i], nxt[i], val[i], len[i]);
    }
    scanf("%s", des);
    int L = strlen(des);
    ans[0] = mn;
    l = 0;
    int idx, pos;
    for (int i = 0; i < L; ++i) {
        if (des[i] == '-') {
            if (l > 0) {
                --l;
            }
            if (l) {
                ans[i + 1] = ans[hi[l]];
            } else {
                ans[i + 1] = mn;
            }
        } else {
            for (int j = 0; j < n; ++j) {
                pos = len[j] + l;

                int kk = i;
                idx = nxt[j][pos];
                while (kk < i + 1) {
                    if (idx == -1 || str[j][idx] == des[i]) {
                        val[j][pos] = (str[j][idx] == des[i] ? val[j][pos] : idx);
                        ++kk;
                        ++idx;
                        nxt[j][pos + 1] = idx;
                    } else {
                        idx = val[j][idx];
                    }
                }
            }
            hi[l] = i;
            ++l;
            ans[i + 1] = mn;
            for (int j = 0; j < n; ++j) {
                ans[i + 1] = min(ans[i + 1], len[j] - nxt[j][len[j] + l] - 1);
            }
        }
    }
    for (int i = 0; i <= L; ++i) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hcx11333/article/details/81781601
今日推荐