贴瓷砖

题目大意及模型转换

给定一个长度为n(n<=3*10^5)的文本串与m(m<=5000)个长度不超过5000的模板。现在将m个模板与文本串进行匹配,输出不可能被匹配到的字符有多少个。

模拟题意

对于字符串匹配的题目,我们可以很快想到kmp算法。
我们可以对每一个模板做kmp算法,然后将每一个模板和文本串做匹配。匹配到的打上布尔标记。
不过,这样会超时,因为匹配的复杂度太大了。

两种方法

想想,还有什么字符串匹配算法?
对文本串进行处理的后缀数组。
对多模板进行处理的AC自动机。

后缀数组

我们求出sa数组后,对于每一个模板,一个字符一个字符逼进。假设目前到第i个字符,排序后的后缀区间l..r中所有后缀前i-1个字符都与该模板前i-1个字符相同。那么我们在区间l..r中寻找新的区间l’..r’,使得l’..r’中所有后缀都与该模板前i个字符相同。然后做完后得到的后缀区间就是匹配成功的地方。

AC自动机

既然是AC自动机那就是裸题了,不讲了。具体实现我们在每个结点上记录深度,这样可以得到匹配成功后的开始位置。
不会AC自动机?戳这里:AC自动洗学习小记by Crazy

统计答案

我们打布尔标记很慢的,怎么办?
我们可以设c[i]表示在i这个位置开始被匹配成功,一直被匹配到i+c[i]-1。
c[i]=0则表示后缀i不存在任何一个前缀能被任意一个模板匹配。
于是就可以了。

 t:=0;
 for i:=1 to n do
 begin
        if t>0 then dec(t);
        if c[rank[i]]>t then t:=c[rank[i]];
        if t=0 then inc(ans);
 end;
 writeln(ans);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值