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. Azure资源管理工具Azure PowerShell介绍

    什么是 Azure PowerShell? Azure PowerShell 是一组模块,提供用于通过 Windows PowerShell 管理 Azure 的 cmdlet.你可以使用 cmdle ...

  2. sysbench0.5安装介绍

    sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况,sysbench支持MySQL.PostgreSQL.Oracle数据库OLTP测试.它 ...

  3. Linux远程连接及常用指令

    一.远程连接 一般,服务器都是特别庞大的,会把它们用一个独立的小屋进行存放,如果有时候需要对服务器进行一些操作,离得近还好,离的远就会破费一些周折了,所以,这个时候我们就需要用到远程连接软件了.推荐使 ...

  4. iphone开发设置默认字体

    It seems to be possible in iOS 5 using the UIAppearance proxy. [[UILabel appearance] setFont:[UIFont ...

  5. Codeforces Round #318 (Div. 2) C Bear and Poker (数学)

    简单题,求一下所有数的2和3的幂是任意调整的,把2和3的因子除掉以后必须相等. 求lcm,爆了long long.我得好好反省一下,对连乘不敏感 #include<bits/stdc++.h&g ...

  6. 用valgrind检查内存问题

    Valgrind Valgrind作为一个免费且优秀的工具包,平时大部分人可能都是使用valgrind检测内存问题,如内存泄露,越界等. Valgrind工具包包含多个工具,如Memcheck,Cac ...

  7. shell脚本,awk合并一列的问题。

    文件 file2内容如下:0 qwert1 asdfghjk2 asdjkl2 zxcvbn3 dfghjkll4 222224 tyuiop4 bnm 让第一列相等的合并成一行,不要第一列,也就是变 ...

  8. javaEE(6)_JSP

    一.什么是JSP 1.JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术,只用JSP就可以开发动态web资源. 2.为什么J ...

  9. ios之UITextfield

    //初始化textfield并设置位置及大小   UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...

  10. 洛谷 P1214 等差数列

    https://www.luogu.org/problemnew/show/P1214 首先暴力枚举可以凑出来的数,对于每个数进行标记. 对于每一个等差数列,当我们知道前两个数后即可以得出整个序列,那 ...