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

来源:互联网 发布:扬州知行广告公司 编辑:程序博客网 时间:2024/06/07 23:37

给你两个字符串,求B的每一个后缀在A中出现的次数与其长度之积。

可以使用extend kmp求得ex【i】(表示对于B与subA(i,strlen(A)-1)的最大匹配前缀);所以我们先反置两个字符串,之后,对于每一个得到的ex【i】,他可以带来的变化是(1+2+3+4+……+i);所以加一个求和函数来得到答案,注意我代码中的ex【i】为int型,在Add函数中,我们如果还是传入int型的话,在运算中会炸。。。转化成longlong就行了

#include<bits/stdc++.h>using namespace std;#define maxn 1000001#define mod 1000000007typedef long long LL;LL ans;int t;char str1[maxn],str2[maxn];int Next[maxn],ex[maxn];void getNext(char str[]){    int i = 0, j, po, len = strlen(str);    Next[0] = len;    while(str[i] == str[i+1]        &&i + 1 < len) i++;    Next[1] = i; po = 1;    for(i = 2; i < len; i++)    {        //         if(Next[i - po] + i < Next[po] + po)            Next[i] = Next[i - po];        else         {            j = Next[po] + po - i;            if(j < 0) j = 0;            while(i + j < len&&str[j] == str[j + i])                j++;            Next[i] = j;            po = i;        }    }}void ex_kmp(char str1[], char str2[]){    int i = 0, j, po, len1 = strlen(str1);    int len2 = strlen(str2);    getNext(str2);    while(str1[i] == str2[i]&&        i < len2&&i < len1) i++;    ex[0] = i;    po = 0;    for(int i = 1; i < len1; i++)    {        if(Next[i - po] + i < ex[po] + po)            ex[i] = Next[i - po];        else         {            j = ex[po] + po - i;            if(j < 0) j = 0;            while(i + j < len1&&j < len2            &&str1[i + j] == str2[j]) j++;            ex[i] = j;            po = i;        }    }}LL add(LL x){    return (x*(x+1))/2%mod;}int main(){    scanf("%d",&t);    while(t--)    {        ans = 0;        scanf("%s%s", str1, str2);        int len1 = strlen(str1);        int len2 = strlen(str2);        reverse(str1,str1+len1);        reverse(str2,str2+len2);        ex_kmp(str1, str2);        for(int i = 0; i < len1; i++)        {            ans = ans + add(ex[i]);            ans %= mod;        }        printf("%lld\n", ans);    }} 
原创粉丝点击