【kmp或扩展kmp】HDU 6153 A Secret
acm.hdu.edu.cn/showproblem.php?pid=6153
【题意】
- 给定字符串A和B,求B的所有后缀在A中出现次数与其长度的乘积之和
- A和B的长度最大为1e6
方法一:扩展kmp
【思路】
- 把A和B同时反转,相当于求B的所有前缀在A中出现次数与其长度的乘积之和
- 换个角度,相当于A中每出现一个B的前缀,答案中就要加上该前缀的长度
- 考虑A中每个位置对答案的贡献,A[i...lenA-1]与B的最长公共前缀是x,则B中的前缀B[0...1],B[0....2]...B[0....x]都在A中出现,那么答案就要加上x*(x+1)/2
- 求S中的每个后缀与T的最长公共前缀用扩展KMP,时间复杂度是线性的
【AC】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+;
const int maxn=1e6+;
char s[maxn];
char t[maxn];
int nxt[maxn];
int extend[maxn];
ll ans; void add(ll n)
{
ll tmp=((n%mod)*((n+)%mod)/)%mod;
ans=(ans+tmp)%mod;
}
void pre_EKMP(char x[],int m,int nxt[])
{
nxt[]=m;
int j=;
while(j+<m && x[j]==x[j+]) j++;
nxt[]=j;
int k=;
for(int i=;i<m;i++)
{
int p=nxt[k]+k-;
int L=nxt[i-k];
if(i+L<p+) nxt[i]=L;
else
{
j=max(,p-i+);
while(i+j<m && x[i+j]==x[j]) j++;
nxt[i]=j;
k=i;
}
}
} void EKMP(char x[],int m,char y[],int n,int nxt[],int extend[])
{
pre_EKMP(x,m,nxt);//子串
int j=;
while(j<n && j<m &&x[j]==y[j]) j++;
extend[]=j;
int k=;
for(int i=;i<n;i++)
{
int p=extend[k]+k-;
int L=nxt[i-k];
if(i+L<p+) extend[i]=L;
else
{
j=max(,p-i+);
while(i+j<n && j<m && y[i+j]==x[j]) j++;
extend[i]=j;
k=i;
}
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
scanf("%s",t);
int ls=strlen(s);
int lt=strlen(t);
for(int i=;i<ls/;i++)
{
swap(s[i],s[ls--i]);
}
for(int i=;i<lt/;i++)
{
swap(t[i],t[lt--i]);
}
EKMP(t,lt,s,ls,nxt,extend);
ans=;
for(int i=;i<ls;i++)
{
add(extend[i]);
}
printf("%I64d\n",ans);
}
return ;
}
扩展kmp
方法二:巧用kmp的next数组
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+;
ll id[maxn];
char s[maxn];
char t[maxn];
int nxt[maxn];
const ll mod=1e9+;
void kmp_pre(char x[],int m,int nxt[])
{
int i,j;
j=nxt[]=-;
i=;
while(i<m)
{
while(-!=j && x[i]!=x[j]) j=nxt[j];
nxt[++i]=++j;
}
} int kmp_count(char x[],int m,char y[],int n)
{
memset(id,,sizeof(id));
int i,j;
ll ans=;
kmp_pre(x,m,nxt);
i=j=;
while(i<n)
{
while(-!=j && y[i]!=x[j])
j=nxt[j];
i++;
j++;
if(i>=n) break;
//失配时记录当前匹配的最长前缀
if(y[i]!=x[j])
{
id[j]++;
}
if(j>=m)
j=nxt[j];
}
//s的结尾出有一段和匹配的,由于i已经达到n没有记录,用t本身的nxt算出
while(j!=-)
{
id[j]++;
j=nxt[j];
}
for(int i=;i<=m;i++)
{
if(id[i])
{
ans=(ans+(1ll*i*(i+)/)%mod*id[i]%mod)%mod;
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
scanf("%s",t);
int ls=strlen(s);
int lt=strlen(t);
reverse(s,s+ls);
reverse(t,t+lt);
ll res=kmp_count(t,lt,s,ls);
cout<<res<<endl;
}
return ;
}
kmp
【kmp或扩展kmp】HDU 6153 A Secret的更多相关文章
- KMP && Manacher && 扩展KMP整理
KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...
- KMP和扩展KMP【转】
这种东西基本上在纸上自己推导一下就能做出来XD 转发注明出处 KMP 给出两个字符串A(称为模板串)和B(称为子串),长度分别为lenA和lenB,要求在线性时间内,对于每个A[i] (0<=i ...
- KMP与扩展KMP
原文转自:http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.aspx KMP:给出两个字符串A(称为模板串)和B(称为子串),长度分别为 ...
- Manacher模板,kmp,扩展kmp,最小表示法模板
*N]; //储存临时串 *N];//中间记录 int Manacher(char tmp[]) { int len=strlen(tmp); ; ;i<len;i++) { s[cnt++]= ...
- HDU 6153 A Secret(扩展KMP模板题)
A Secret Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Others) Total ...
- HDU 6153 A Secret(扩展kmp)
A Secret Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Others)Total ...
- KMP和扩展KMP
文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...
- kmp模板 && 扩展kmp模板
kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...
- KMP 、扩展KMP、Manacher算法 总结
一. KMP 1 找字符串x是否存在于y串中,或者存在了几次 HDU1711 Number Sequence HDU1686 Oulipo HDU2087 剪花布条 2.求多个字符串的最长公共子串 P ...
随机推荐
- SQL——SQL语言全部关键字详解
http://blog.csdn.net/quinnnorris/article/details/71056445 数据库中我们做常用的就是SQL基本查询语言,甚至有些人认为数据库就是SQL,SQL就 ...
- valgrind测试程序内存泄漏问题
1.用wincap将valgrind放入系统任意路径下,解压 2. 登录主机后台在需要测试程序的路径下运行此行命令: /opt/valgrind/bin/valgrind ./itb(例) 3. 跑 ...
- 快学UiAutomator配置编辑环境
Java环境配置 1.下载jdk1.6+包 2.安装jdk,默认安装即可 3.成功安装之后,进行测试是否真的成功安装,点击[开始]----[运行]----输入 CMD,在命令提示符里面输入“Java ...
- 菜鸟教你如何通俗理解——>集群、负载均衡、分布式
在“高并发,海量数据,分布式,NoSql,云计算......”概念满天飞的年代,相信不少朋友都听说过甚至常与人提起“集群,负载均衡”等,但不是所有人都有机会真正接触到这些技术,也不是所有人都真正理解了 ...
- 【Java_Spring】控制反转IOC(Inversion of Control)
1. IOC的概念 控制反转IoC(Inversion of Control)是一种设计思想,而DI(依赖注入)是实现IoC的一种方法.在没有使用IOC的程序中,对象间的依赖关系是靠硬编码的方式实现的 ...
- grafana绘制图表
安装方法 系统为ubuntu16 1首先添加以下到/etc/apt/sources.list: deb https://packagecloud.io/grafana/stable/debian/ s ...
- 老男孩Python高级全栈开发工程师【真正的全套完整无加密】
点击了解更多Python课程>>> 老男孩Python高级全栈开发工程师[真正的全套完整无加密] 课程大纲 老男孩python全栈,Python 全栈,Python教程,Django ...
- Shell中各种括号的作用
一.小括号,圆括号() 1.单小括号 () ① 命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号 ...
- 条款40:明智而审慎地使用多重继承(use multiple inheritance judiciously)
NOTE: 1.多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. 2.virtual 继承会增加大小 速度 初始化(及赋值)复杂度等等成本.如果virtual base ...
- python datetime,time时间格式和用法
我是转载的这个大神的 他的网址:https://www.cnblogs.com/wanglinjie/p/9226926.html #以下是time的方法 >>> import ...