列表

详情


NC17681. 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.

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 22ms, 内存消耗: 13892K, 提交时间: 2018-08-17 15:28:57

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
const int INF=1e9+7;
typedef long long ll;
int ans[MAX],f[MAX];
int pre[MAX][30];
void getfail(char *s,int n)
{
    f[0]=f[1]=0;
    for(int i=1;i<n;i++)
    {
        int j=f[i];
        while(j&&s[i]!=s[j])j=f[j];
        f[i+1]=(s[i]==s[j]?j+1:0);
    }
    for(int i=0;i<=n;i++)
    for(int j=0;j<26;j++)
    {
        pre[i][j]=(i==0?0:pre[f[i]][j]);
        if(i<n)pre[i][s[i]-'a']=i+1;
    }
}
int tp[MAX];
void kmp(char *s,char *p,int m,int n)
{
    ans[0]=min(ans[0],m);
    getfail(s,m);
    int cur=0;
    tp[0]=0;
    for(int i=0;i<n;i++)
    {
        if(p[i]=='-')cur=max(cur-1,0);
        else tp[cur]=pre[tp[cur++]][p[i]-'a'];
        ans[i+1]=min(ans[i+1],m-tp[cur]);
    }
}
char s[5][MAX],p[MAX];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%s",s[i]);
    scanf("%s",p);
    int m=strlen(p);
    for(int i=0;i<=m;i++)ans[i]=INF;
    for(int i=1;i<=n;i++)kmp(s[i],p,strlen(s[i]),m);
    for(int i=0;i<=m;i++)printf("%d\n",ans[i]);
    return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 19ms, 内存消耗: 2096K, 提交时间: 2022-08-09 16:24:23

#include<bits/stdc++.h>
using namespace std;
const int N=2000009;
void KMP(char *x,int *fail)
{
	int len=strlen(x);
	int i=0,j=-1;
	fail[0]=-1;
	while(i<len)
	{
		while(j!=-1&&x[i]!=x[j]) j=fail[j];
		fail[++i]=++j;
		if(x[i]==x[j])
		fail[i]=fail[j]; 
	 } 
}
char x[5][N],a[N];
int fail[N];
int ans[N];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	scanf("%s",x[i]);
	scanf("%s",a);
	int len=strlen(a);
	for(int i=0;i<=len;i++)
	ans[i]=1e9;
	int mi=1e9;
	for(int i=1;i<=n;i++)
	{
		int lens=strlen(x[i]);
		mi=min(mi,lens);
		KMP(x[i],fail);
		stack<int>q;
		int now=0;
		for(int j=0;j<len;j++)
		{
			if(a[j]=='-')
			{
				if(!q.empty()) q.pop();
				if(!q.empty()) now=q.top();
				else now=0;
			}
			else
			{
				while(x[i][now]!=a[j]&&now!=-1)
				now=fail[now];
				q.push(++now);
			}
			ans[j]=min(ans[j],lens-now);
		}
	}
	printf("%d\n",mi);
	for(int i=0;i<len;i++)
	printf("%d\n",ans[i]);
}

上一题