hdu 6153 A Secret(kmp||扩展kmp)
来源:互联网 发布:蓝牙耳机控制软件 编辑:程序博客网 时间:2024/06/05 15:00
A Secret
题目链接:A Secret
题意:给定两个字符串s1和s2,对于s2的每个后缀,
思路:可以先把后缀转换为前缀,然后就是扩展kmp的模板题了。
在扩展kmp中,next[i]表示T[i,len_T-1]与T[0,len_T-1]的最长公共前缀,
extend表示S[i,len_S-1]与T[0,len_T-1]的最长公共前缀
代码:
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int mod=1e9+7;const int maxn=1e6+10;int Next[maxn],extend[maxn];string s1,s2;int len1,len2;LL Calc(LL x){ return (x*(x+1)/2)%mod;}void Get_next(){ int i=0; Next[0]=len2; while(i<len2&&s2[i]==s2[i+1]) ++i; Next[1]=i; int a=1; for(int k=2; k<len2; ++k) { int p=a+Next[a]-1,l=Next[k-a]; if(k+l>p) { int j=(p-k+1)>0?(p-k+1):0; while(k+j<len2&&s2[j]==s2[k+j]) ++j; Next[k]=j,a=k; } else Next[k]=l; }}void Ex_kmp(){ Get_next(); int a=0,Min_len=len1<len2?len1:len2; while(a<Min_len&&s1[a]==s2[a]) ++a; extend[0]=a,a=0; for(int k=1; k<len1; ++k) { int p=a+extend[a]-1,l=Next[k-a]; if(k+l>p) { int j=(p-k+1)>0?(p-k+1):0; while(k+j<len1&&j<len2&&s1[k+j]==s2[j]) ++j; extend[k]=j,a=k; } else extend[k]=l; }}int main(){ std::ios::sync_with_stdio(false); int t; cin>>t; while(t--) { cin>>s1>>s2; reverse(s1.begin(),s1.end()); reverse(s2.begin(),s2.end()); len1=s1.length(),len2=s2.length(); Ex_kmp(); LL ans=0; for(int i=0; i<len1; ++i) if(extend[i]) ans=(ans+Calc(extend[i]))%mod; cout<<ans<<endl; } return 0;}
扩展kmp学习推荐ppt:扩展的KMP算法-刘雅琼
扩展kmp学习博客:yefeng 1627
大佬的kmp做法
思路:在kmp匹配的过程中,if(j&&s1[i]!=s2[j])
,同时对当前匹配的长度j进行记录,表示s2中长度为j的前缀在s1中出现了一次
因为每次记录的都是最长的前缀,所以需要(在随着长度递减的同时)对cnt[i]递加求和
代码:
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int maxn=1e6+10;const int mod=1e9+7;int nxt[maxn];LL cnt[maxn];void Get_next(string str){ for(int i=1,j=0; i<str.length(); ++i) { while(j&&str[j]!=str[i]) j=nxt[j]; if(str[i]==str[j]) ++j; nxt[i+1]=j; }}void Kmp_count(string s1,string s2){ Get_next(s2); s1[s1.length()]='#'; for(int i=0,j=0; i<=s1.length(); ++i) { while(j&&s1[i]!=s2[j]) ++cnt[j],j=nxt[j]; if(s1[i]==s2[j]) ++j; if(j==s2.length()) ++cnt[j],j=nxt[j]; }}int main(){ std::ios::sync_with_stdio(false); int t; cin>>t; while(t--) { string s1,s2; memset(cnt,0,sizeof(cnt)); cin>>s1>>s2; reverse(s1.begin(),s1.end()); reverse(s2.begin(),s2.end()); Kmp_count(s1,s2); LL ans=0; for(int i=s2.length(); i; --i) { cnt[i]=(cnt[i]+cnt[i+1])%mod; ans=(ans+cnt[i]*i%mod)%mod; } cout<<ans<<endl; } return 0;}
阅读全文
1 0
- HDU 6153 A Secret【KMP||扩展KMP】
- hdu 6153 A Secret KMP&&扩展KMP
- HDU 6153 A Secret (扩展KMP)
- HDU 6153 A Secret(扩展KMP)
- A Secret(HDU 6153 扩展KMP)
- HDU 6153 A Secret(KMP/扩展KMP)
- hdu 6153 A Secret(kmp||扩展kmp)
- 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模板题)
- HDU 6153 A Secret(扩展KMP算法)
- HDU 6153 A Secret(扩展KMP+数学推导)
- hdu6153-A Secret (kmp/扩展kmp)
- HDU 6153-A Secret(kmp&&ccpc)
- HDU 6153 A Secret(KMP)
- HDU 6153A Secret(kmp)
- 数论基础(浅谈数论的部分实现)
- mysql引擎
- App 后台架构
- 继承是什么?
- 用stat写出ls -l 的功能
- hdu 6153 A Secret(kmp||扩展kmp)
- Vim 常用操作命令整理
- python之正则表达式的用法总结
- Android中ConvenientBanner的使用--获取本地图片 --(实现效果是自动轮播图片)
- validate和bootstrap的使用
- AOP之使用AspectJ案例
- skynet 常用lua函数汇总
- ERDAS大气校正
- RUP,极限编程与敏捷过程的概念