1. 程式人生 > >2018第九場暑期牛客多校 F --- KMP

2018第九場暑期牛客多校 F --- KMP

題意:

       給定n(<4)個字串,然後有一個操作:逐個輸入一個長為L字串,字串中出現 減號 代表刪除一個字元,問每次輸入一個字元或者刪除一個字元後再輸入最少多少個 字尾能出現前面n個字串之一.

分析:

       KMP演算法:用前面n個字串逐個去匹配後面的操作字串,所求答案為m-j. 但是刪除怎麼處理呢,用棧去維護. 但是這道題是卡MP演算法的失配函式的. 極限情況如下:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-b-b-b-b-b(前面有一大把a)

這種情況會卡掉(複雜度無法均攤,會來到n方的複雜度).仔細結合程式碼好好想想.

 

連結: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

 

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define oo cout<<"!!!"<<endl;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
//head

const int maxn = 1e5+1111;
int f[maxn],f2[maxn];
int mv[maxn];
void getfail(char * P)
{
	int m = strlen(P);
	f[0] = f[1] = 0;
	f[0] = f2[1] = 0;
	for(int i = 1;i<m;i++)
	{
		int j = f2[i];
		while(j && P[i] != P[j])j = f2[j];
		f2[i+1] = f[i+1] = (P[i]==P[j])? j+1:0;
		if(f[i+1] == j+1 && P[i+1] == P[j+1])f[i+1] = f[j+1]; 
	} 
}
void find(char *P,char *T)
{
	int n = strlen(T);
	int m = strlen(P);
	getfail(P);
	int j = 0;
	stack<int>st;
	st.push(0);
	rep(i,0,n)
	{
		if(T[i] == '-')
		{
			if(st.size()>1)
			st.pop(),
			j = st.top();
		}
		else
		{
			while(j && P[j] != T[i])j = f[j];//如果不優化失配函式,這裡會被卡掉的
			if(P[j] == T[i])j++;
			st.push(j);
		}
		mv[i] = min(mv[i],m-st.top()); 
	}
}
int main() 
{
	int n;
	cin>>n;
	char ch[4][maxn];
	char pro[maxn];
	int x=inf;
	int tmp;
	rep(i,0,n)scanf("%s",ch[i]),tmp = strlen(ch[i]),x = min(x,tmp);
	scanf("%s",pro);
	fill(mv,mv+strlen(pro)+11,inf);

	rep(i,0,n)
		find(ch[i],pro);

	printf("%d\n",x);
	rep(i,0,strlen(pro))
		printf("%d\n",mv[i]);


    return 0;
}