Typing practice

链接: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.

相似题型 

#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i=a;i<b;i++)

const int maxn=1e5+100;

char s[4][maxn];
char str[maxn];


int fail[maxn],f[maxn];
void getFail(char *P,int len)
{
    fail[0] = fail[1] = 0; //压缩路径的失配指针
    f[0]=f[1]=0;           //正常的失配指针,也就是[0,i-1]的最大前缀后缀
    for(int i = 1; i < len; i++)
    {
        int j = f[i];
        while(j && P[i] != P[j] ) j = f[j];//没有可匹配,或者能找到匹配的P[j] ==T[i]
        fail[i+1] = f[i + 1] = (P[i] == P[j]) ? j + 1 : 0;
        //既然i+1的失配位置指向j+1,但是P[i+1]和P[j+1]的内容是相同的
        //所以就算指针从i+1跳到j+1去,还是不能匹配,所以f[i+1]直接=f[j+1]
        if(fail[i+1]==j+1 && P[i+1]==P[j+1]) fail[i+1]=fail[j+1];
    }
}

int sum=maxn;
int len;
int ans[maxn],stk[maxn];//stk[i]的意思是 [0,i]的文本串和 模式串的最大匹配长度(对应的j)

/*

为什么要使用真正的KMP?
考虑模版串是 aaaaaaaaaaaaaaa....,如果这样超级长,
而且文本串是 这种 aaaaaaaaaaaaabaaaaaaaaaab....就是好不容易j跳到了末尾,然后不匹配又得一个一个的跳回来
所以这样就会非常浪费时间,如果压缩了的话,就会发现直接回到0
比如ABABC, 事实上,如果和第二个B不匹配的话,和第一个B也完全不会匹配,因为他们两个串相等,也就是AB AB,所以可以直接跳回第一个B失配的位置。
    00012
*/

void solve(char* T,char* P,int num){
    int m = strlen(P);
    sum=min(sum,m);
    getFail(P,m);
    int j=0,top = -1;
    for(int i =  0;i < len; ++i){
       if(str[i]=='-'){
         if(top>-1)--top;
         j=top==-1?0:stk[top]; //对于退回来的时候的 j 的赋值比较难理解,其实还是[0,top]的最大匹配长度,同时也是和 文本串 stk[top+1] 比较的 模版串的j号下标的字符,也就是为下一个字符比较做好准备 
       }
       else{
         while(j&&T[i]!=P[j])j=fail[j];
         if(T[i]==P[j])++j;
         stk[++top]=j;
       }
       ans[i]=min(ans[i],m-j);//j是存在的文本串和模版串的最大匹配长度
    }
}

int main(){
    int n;
    scanf("%d",&n);
    rep(i,0,n)scanf("%s",s[i]);

    scanf("%s",str);
    len=strlen(str);

    fill(ans,ans+len,maxn);
    rep(i,0,n)  solve(str,s[i],i);
    printf("%d\n",sum);
    rep(i,0,len)printf("%d\n",ans[i]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值