链接:https://www.nowcoder.com/acm/contest/147/F
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
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.
题意:给你最多4个字符串(长度<=1e5),然后给你一个操作序列(txt字符串)。是这样的:
你每输入一个字符(刚开始空的字符串也算),就输出至少要在你当前输入的字符串上后面补几个字母才能使前面给的串正好是你补完之后的串的后缀。而且操作序列中包含'-',就是退格,删除你前一个输入的字符。如果当前字符串是空的,那么什么也没发生,当做空串处理。
思路:比赛时想开4个kmp,每个记录nex数组,然后每输入一个字符就开始更新。。。结果遇到形如aaaa,aaaab-b-b-b-这样的复杂度就会退化为n*m,然后就不会了。其实这个思路是可行的,不过需要优化(有大神用了另一个数组,保证失败以后一定到达一个不同的字母的下一个地方,这样就可以了)。还有就是题解说是字典树,貌似也能搞,不太清楚。而我赛后看了一个AC自动机的代码,非常神奇,理解之后自己又去敲了一遍。其实就是利用了ac自动机建图的特点,先对4个单词建图,然后将图中是单词尾节点的节点和失配指针指向的是单词尾节点的节点都标记ans[i]=1并加入队列中。然后对于每个队列的节点u,往上跳其父节点v,则ans[v]=ans[u]+1。再将v加入队列中。ans值不为0的当然就直接跳过。最后查询的时候,从根节点开始,每出入一个字符,就沿AC自动机的根节点往下走,假设对应的节点下标是v,则答案就是ans[v]-1。(因为正好差最少ans[v]-1个字符走到尾节点,仔细想想是不是)然后套个AC自动机的模板就可以了。注意细节的修改。这样时间复杂度应该是O(N*L+M)的自己xjb乱算的。其实这道题主要在于思维,工具就是KMP、字典树和AC自动机。只要善于理解运用,这道题就很容易解决了。以后还要多加练习。。。
代码:
#include
using namespace std;
const int mx=400100;
const int ssize=26;
int ans[mx],re[mx];
queueqq;
vectorvc[mx];
struct ACzdj{
int ch[mx][ssize];
int val[mx];
int f[mx];
int last[mx];
int cnt[mx];
int sz;
void init()
{
memset(ch[0],0,sizeof(ch[0]));
memset(cnt,0,sizeof(cnt));
val[0]=0;
f[0]=last[0]=0;
sz=1;
}
void insert(char *s)
{
int n=strlen(s),u=0;
for(int i=0;i q;
f[0]=0;
for(int i=0;i