HDU 6153 A Secret

题意:给定两个串,求其中一个串 s 的每个后缀在另一个串 t 中出现的次数。

题解:把两个串都 reverse 一下,给 t 做个 KMP 之后让 s 在 KMP 出来的结果上跑一遍就好了。

kmp模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define lson i<<1
#define rson i<<1|1
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
char s[N],t[N];
int f[N],cnt[N];
int n,m;
void getnext()
{
    f[0]=f[1]=0;
    for(int i=1;i<m;i++)
    {
        int j=f[i];
        while(j&&s[i]!=s[j])
            j=f[j];
        f[i+1]=(s[i]==s[j])?j+1:0;
    }
}
void kmp()
{
    memset(cnt,0,sizeof(cnt));
    for(int i=0,j=0;i<n;i++)
    {
        while(j&&t[i]!=s[j])
            j=f[j];
        j+=(t[i]==s[j]);
        cnt[j]++;
    }
    for(int i=m;i>0;i--)
        cnt[f[i]]+=cnt[i];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",t,s);
        n=strlen(t);
        m=strlen(s);
        reverse(t,t+n);
        reverse(s,s+m);
        getnext();
        kmp();
        int ans=0;
        for(int i=1;i<=m;i++)
            ans=(ans+1LL*i*cnt[i]%mod)%mod;
        printf("%d\n",ans);
    }
    return 0;
}

  

时间: 2024-10-18 12:00:35

HDU 6153 A Secret的相关文章

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

A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Total Submission(s): 2523    Accepted Submission(s): 934 Problem Description Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,w

HDU 6153 A Secret 套路,求解前缀在本串中出现的次数

http://acm.hdu.edu.cn/showproblem.php?pid=6153 首先相当于翻转两个串,然后求s2前缀在s1中出现的次数. 这是一个套路啦 首先把两个串结合起来,中间加一个'%'之类的分割 设dp[i]表示前缀1---i在本串中的出现次数和 那么从后开始dp,所有dp值一开始都是1,表示前缀出现了一次,就是自己本身. 转移,设当前去到第i位,则dp[next[i + 1] - 1] += dp[i] 就是ABACABA这样,已经知道了ABACABA出现了一次,然后前后

【扩展kmp】HDU 6153 A Secret

acm.hdu.edu.cn/showproblem.php?pid=6153 [题意] 给定字符串A和B,求B的所有后缀在A中出现次数与其长度的乘积之和 A和B的长度最大为1e6 [思路] 把A和B同时反转,相当于求B的所有前缀在A中出现次数与其长度的乘积之和 换个角度,相当于A中每出现一个B的前缀,答案中就要加上该前缀的长度 考虑A中每个位置对答案的贡献,A[i...lenA-1]与B的最长公共前缀是x,则B中的前缀B[0...1],B[0....2]...B[0....x]都在A中出现,那

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6153 A Secret KMP,思维

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:给了串s和t,要求每个t的后缀在在s中的出现次数,然后每个次数乘上对应长度求和. 解法:关键在于想到把s和t都翻转之后,把t求next,然后用t去匹配s,在匹配过程中把fail指针跳到的地方加1,但是还没完,最后需要反向遍历第二个串将大串对小串的贡献加上去就可以了. 这道题是很多现场AC的代码是有漏洞的,比如bazbaba,bazbaba这个答案是34,但是很多现场AC的代码会输出31.

HDU 6153 A Secret(扩展kmp)

A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)Total Submission(s): 1530    Accepted Submission(s): 570 Problem Description Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,wh

HDU 6153 A Secret (KMP)

题意:给定两个串,求其中一个串 s 的每个后缀在另一个串 t 中出现的次数. 析:首先先把两个串进行反转,这样后缀就成了前缀.然后求出 s 的失配函数,然后在 t 上跑一遍,如果发现不匹配了或者是已经完全匹配了,要计算,前面出现了多少个串的长度匹配也就是 1 + 2 + 3 + .... + j 在 j 处失配,然后再进行失配处理.注意别忘了,匹配完还要再加上最后的. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000"

A Secret hdu 6153

KMP的一道水题,最初竟然傻逼的想用自动机怼,毫无疑问的T了,后来仔细想了一下,就是自动自单链的情况,就怼kmp,然后不知道发什么神经没有转过来弯,竟然没调出来,然后我就自己写了单链的fail指针,调了很久A了,但是浪费了很多时间,赛后想想,特么的就是个kmp,next数组跟fail指针就特么差一位而已,果然,套个板子就A了,要不然,今天又可以多出一题了,警示自己一下,不要那么菜啊~~~~ #include <stdio.h> #include <algorithm> #inclu

hdu 6153

http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:有两个字符串,第一个是母串,第二个是子串,问子串的前缀可以匹配多少个母串,然后在乘以它的长度的总和 思路:把字符串反过来,用kmp匹配,然后匹配的时候统一一下这个串出现过多少次,然后还有就是这个串的子串出现的次数一定要加上它 因为如果可以匹配后面的,那么前面的也是一定可以匹配的.那么也就是前面的也是它的子串 1 #include <stdio.h> 2 #include <string.h

HDU 6153 KMP

HDU6153:http://acm.hdu.edu.cn/showproblem.php?pid=6153 Orz 果然字符串很神奇--(神奇到人哭出来啊TAT)果然算法理解的不够透彻的话,是无法灵活运用的QAQ 其实只要简单的改一点点KMP的地方-- KMP的next[i]存储的是模式串下标0至i处相同的前缀和后缀的最长长度,每次与目标串匹配的时候,会略过前后缀相同的部分以减少回溯,提高效率. 由于每次匹配都是从前向后匹配的,因此对于模式串每次的匹配子串都是[0--i],是前缀,但是根据题目