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的更多相关文章

  1. KMP && Manacher && 扩展KMP整理

    KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...

  2. KMP和扩展KMP【转】

    这种东西基本上在纸上自己推导一下就能做出来XD 转发注明出处 KMP 给出两个字符串A(称为模板串)和B(称为子串),长度分别为lenA和lenB,要求在线性时间内,对于每个A[i] (0<=i ...

  3. KMP与扩展KMP

    原文转自:http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.aspx KMP:给出两个字符串A(称为模板串)和B(称为子串),长度分别为 ...

  4. Manacher模板,kmp,扩展kmp,最小表示法模板

    *N]; //储存临时串 *N];//中间记录 int Manacher(char tmp[]) { int len=strlen(tmp); ; ;i<len;i++) { s[cnt++]= ...

  5. HDU 6153 A Secret(扩展KMP模板题)

    A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Total ...

  6. HDU 6153 A Secret(扩展kmp)

    A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)Total ...

  7. KMP和扩展KMP

    文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...

  8. kmp模板 && 扩展kmp模板

    kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...

  9. KMP 、扩展KMP、Manacher算法 总结

    一. KMP 1 找字符串x是否存在于y串中,或者存在了几次 HDU1711 Number Sequence HDU1686 Oulipo HDU2087 剪花布条 2.求多个字符串的最长公共子串 P ...

随机推荐

  1. SQL——SQL语言全部关键字详解

    http://blog.csdn.net/quinnnorris/article/details/71056445 数据库中我们做常用的就是SQL基本查询语言,甚至有些人认为数据库就是SQL,SQL就 ...

  2. valgrind测试程序内存泄漏问题

    1.用wincap将valgrind放入系统任意路径下,解压 2.  登录主机后台在需要测试程序的路径下运行此行命令: /opt/valgrind/bin/valgrind ./itb(例) 3. 跑 ...

  3. 快学UiAutomator配置编辑环境

    Java环境配置 1.下载jdk1.6+包 2.安装jdk,默认安装即可 3.成功安装之后,进行测试是否真的成功安装,点击[开始]----[运行]----输入 CMD,在命令提示符里面输入“Java ...

  4. 菜鸟教你如何通俗理解——>集群、负载均衡、分布式

    在“高并发,海量数据,分布式,NoSql,云计算......”概念满天飞的年代,相信不少朋友都听说过甚至常与人提起“集群,负载均衡”等,但不是所有人都有机会真正接触到这些技术,也不是所有人都真正理解了 ...

  5. 【Java_Spring】控制反转IOC(Inversion of Control)

    1. IOC的概念 控制反转IoC(Inversion of Control)是一种设计思想,而DI(依赖注入)是实现IoC的一种方法.在没有使用IOC的程序中,对象间的依赖关系是靠硬编码的方式实现的 ...

  6. grafana绘制图表

    安装方法 系统为ubuntu16 1首先添加以下到/etc/apt/sources.list: deb https://packagecloud.io/grafana/stable/debian/ s ...

  7. 老男孩Python高级全栈开发工程师【真正的全套完整无加密】

    点击了解更多Python课程>>> 老男孩Python高级全栈开发工程师[真正的全套完整无加密] 课程大纲 老男孩python全栈,Python 全栈,Python教程,Django ...

  8. Shell中各种括号的作用

    一.小括号,圆括号() 1.单小括号 () ① 命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号 ...

  9. 条款40:明智而审慎地使用多重继承(use multiple inheritance judiciously)

    NOTE: 1.多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. 2.virtual 继承会增加大小 速度 初始化(及赋值)复杂度等等成本.如果virtual base ...

  10. python datetime,time时间格式和用法

    我是转载的这个大神的   他的网址:https://www.cnblogs.com/wanglinjie/p/9226926.html #以下是time的方法 >>> import ...