HDU 6153 A Secret CCPC网络赛,KMP拓展应用
来源:互联网 发布:影楼后期排版软件 编辑:程序博客网 时间:2024/06/05 15:30
传送门:HDU 6153
2aaaaaaaabababababa
1319
题目大意:输入两个字符串s,t,设长度分别为ls和lt,下标从1开始,求t的所有后缀t[i..lt]在s中出现的次数乘以后缀长度的和。注意,这里的后缀是可重叠的。例如s="abababab",t="aba",后缀aba在s中出现3次,ab出现3次,a出现4次。ans=3*3+3*2+4*1=19.
前置技能:拓展KMP算法,用于求一个串的所有前缀与另一个串的最长公共前缀的长度。比如“abcabac”与“abcb”的最长公共前缀为“abc”。
思路:第一想法是直接用KMP算法求每个后缀在s中出现的次数,然后分别乘以后缀的长度并相加。但是会超时。考虑到我们做了大量的重复运算,可以把s和t字符串都翻转过来得到s'和t'。这样求t的后缀在s中出现的次数就变成了求t'的前缀在s'中出现的次数。当匹配到 i 失配时,说明前 i-1 个前缀都可以匹配,大大减少了重复运算。但是这样一来,原来的KMP算法就不再适用了。因为有些情况是匹配不到的。比如s="acab",t="ab",s'="baca",t'="ba",前缀a在s'中出现了两次,但是却只能匹配到一次。这时可以用拓展KMP算法求出s'的每个前缀和t'的最长公共前缀的长度。当s'的前缀与t'的最长公共前缀长度为n时,说明从当前位置开始有n个前缀可以匹配,他们的长度和为 1+2+…+n = (n+1)*n/2 ,只要将得到的公共前缀的长度求和就好了。
具体实现:先将两个字符串翻转,再调用一次拓展KMP算法求最长公共前缀的长度extend[i],每个最长公共前缀对结果的贡献是 extend[i]*(extend[i]-1)/2 ,相加并取模即可。
#include<stdio.h>#include<string.h>typedef long long LL;int ls,lt;int mod=1e9+7;char s[1000010],t[1000010];int next[1000010],extend[1000010];void get_next(){ int i,a=0,p=0; next[0]=lt; for(i=1;i<lt;i++) {if(i>=p || i+next[i-a]>=p){if(i>=p) p=i;while(p<lt && t[p]==t[p-i]) p++;next[i]=p-i;a=i;}else next[i]=next[i-a];}}void ex_kmp(){int i,a=0,p=0;get_next();for(i=0;i<ls;i++){if(i>=p || i+next[i-a]>=p){if(i>=p) p=i;while(p<ls && p-i<lt && s[p]==t[p-i])p++;extend[i]=p-i;a=i;}else extend[i]=next[i-a];}}int main(){int i,tt;char c;LL ans;scanf("%d",&tt);while(tt--){scanf("%s%s",s,t);ls=strlen(s);lt=strlen(t);for(i=0;i<ls/2;i++){ //将字符串s翻转 c=s[i];s[i]=s[ls-1-i];s[ls-1-i]=c;}for(i=0;i<lt/2;i++){ //将字符串t翻转c=t[i];t[i]=t[lt-1-i];t[lt-1-i]=c;}ex_kmp(); //调用拓展KMP求最长公共前缀 ans=0;for(i=0;i<ls;i++){ //求结果 ans+=((LL)extend[i]*(extend[i]+1)/2)%mod;ans%=mod;}printf("%lld\n",ans);}return 0;}
- HDU 6153 A Secret CCPC网络赛,KMP拓展应用
- HDU 6153-A Secret(kmp&&ccpc)
- HDU-6153---A Secret (扩展kmp)(2017ccpc网络赛)
- HDU 6153 A Secret(拓展KMP)
- 【KMP+优化】HDU 6153/CCPC 1003 A Secret
- HDU 6153 A Secret(后缀转前缀+拓展KMP)
- A Secret 2017 CCPC 网络选拔赛 hdu 6153
- ccpc 2017 网络赛 1004 A Secret (扩展kmp)【模板】
- hdu 6153 A Secret KMP
- HDU 6153 A Secret KMP
- HDU 6153 A Secret KMP
- Hdu 6153 A Secret【KMP】
- 【KMP】HDU 6153 A Secret
- HDU 6153 A Secret(KMP)
- hdu 6153 A Secret (kmp)
- hdu 6153 A Secret (KMP)
- hdu 6153 A Secret(KMP)
- hdu 6153 A Secret(KMP)
- iOS项目使用cocoPods 管理百度地图SDK
- android小圆点
- Oracle字符串截取
- tkinter的GUI设计:界面与逻辑分离(二)-- 菜单栏
- 【NOIP2000提高】乘积最大
- HDU 6153 A Secret CCPC网络赛,KMP拓展应用
- 使用Jsoup解析html数据
- 水题数位dp 0~9
- Google算法题:扔鸡蛋/扔棋子
- 机器学习----lightGBM安装
- Java MacUtil 获取mac地址 工具类
- 获取某个目录下所有文件夹名和文件名
- 什么是 JWT -- JSON WEB TOKEN
- 1070: [SCOI2007]修车