当前位置: 代码迷 >> 综合 >> [牛客网暑期ACM多校训练营(第九场)] F Typing practice [KMP ]
  详细解决方案

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

热度:21   发布时间:2023-11-10 01:12:12.0

链接:https://www.nowcoder.com/acm/contest/147/F
来源:牛客网

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.

分析: 我们简化一下问题,如果n==1的话,可以怎么解决? 直接操作串作为母串,words串作为模式串 进行KMP, 如果操作串中没有’-‘操作,那么就是KMP了,但是现在还有减字符,这怎么办 ? 模式串的指针重头开始? 那么太慢了, 其实删掉一个字符,也就是模式串的指针回到截止到上一个字符的指针就好了,这里我们可以用栈来保存 .
如果n == 4, 我们只需要做n次就行了,每次每个位置不断取最小.
代码

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <list>
#include <string>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, l, r) for(int i = l; i < r; i++)
#define per(i, r, l) for(int i = r; i >= l; i--)typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;const int N = (int) 1e5 + 11;
const int M = (int) 1e6 + 11;
const int MOD = (int) 1e9 + 7;
const double EPS = (double) 1e-9;
const double PI = (double)acos(-1.0);
const int INF = (int) 0x3f3f3f3f;
const ll INFF = (ll) 0x3f3f3f3f3f3f3f3f;ll add(ll x, ll y){
   return (x += y) >= MOD ? x - MOD : x;}
ll sub(ll x, ll y){
   return (x -= y) < 0 ? x + MOD : x;}
void read(int &x){char ch = getchar(); x = 0;while(ch < '0' || ch > '9') ch = getchar();while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
}
/*-----------------------------------------------------------------------------------*/ void pre_work(char *s, int *nxt){ // 优化后的nxt, 不然会Tint i, j; int n =strlen(s);i = 0;  j = nxt[0] = -1;while(i < n) {while(j != -1 && s[j] != s[i]) j = nxt[j];++j; ++i;if(s[j] == s[i]) nxt[i] = nxt[j];else nxt[i] = j;}
}int nxt[N];
char op[N], s[5][N]; int len[5], fail[N], top, ans[N];
int main(){#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);#endifint n; while(~scanf("%d", &n)){int mn = INF;rep(i, 0, n) scanf("%s", s[i]), len[i] = strlen(s[i]), mn = min(mn, len[i]);scanf("%s", op); int L = strlen(op);rep(i, 0, L) ans[i] = mn;rep(I, 0, n){int top = 0; int j = 0; fail[0] = -1;pre_work(s[I], nxt);rep(i, 0, L){ // 核心代码if(op[i] == '-'){top = max(top - 1, 0);j = fail[top];// 回到上一个的状态就好}else {while(j != -1 && s[I][j] != op[i]) j = nxt[j];fail[++top] = j; // 记录一定匹配(或是j==-1)时候的指针j}++j;ans[i] =  ans[i] > (len[I] - j) ? (len[I] - j) : ans[i];}}printf("%d\n", mn);rep(i, 0, L) printf("%d\n", ans[i]);}return 0;
}
  相关解决方案