HDU 6153 A Secret(KMP/扩展KMP)

来源:互联网 发布:卸载软件工具下载 编辑:程序博客网 时间:2024/06/05 20:59

题目:http://acm.hdu.edu.cn/showproblem.php?pid=6153
题意:给你串s,串p,求∑(p的后缀在s中出现的次数*长度)
思路:将串都反转后,转化为求前缀,可利用kmp求解
代码:

拓展KMP:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MOD = 1e9+7;const int N = 1e6+5;char s[N],p[N];int Next[N],extend[N];long long sum[N];void GetNext(char *t){    int len = strlen(t);    int a = 0;    Next[0] = len;    while(a < len - 1 && t[a] == t[a+1])        a++;    Next[1] = a;    a = 1;    for(int k = 2;k < len;k++)    {        int p = a + Next[a] - 1,L = Next[k-a];        if((k-1)+L >= p)        {            int j = (p-k+1) > 0?p-k+1:0;            while(k + j < len && t[k+j] == t[j])                j++;            Next[k] = j;            a = k;        }        else            Next[k] = L;    }}void GetExtend(char *s,char *t){    int a = 0;    GetNext(t);    int len1 = strlen(s);    int len2 = strlen(t);    int minlen = min(len1,len2);    while(a < minlen && s[a] == t[a])        a++;    extend[0] = a;    a = 0;    for(int k = 1;k < len1;k++)    {        int p = a+extend[a]-1,L = Next[k-a];        if((k-1)+L >= p)        {            int j = (p-k+1) >0 ?p-k+1:0;            while(k+j < len1 && j<len2 &&s[k+j] == t[j])                j++;            extend[k] = j;            a = k;        }        else            extend[k] = L;    }}void Getfail(char *t){    int len = strlen(t);    int i = 0, j = -1;    Next[0] = -1;    while(i < len)    {        if(j == -1 || t[i] == t[j])            Next[++i] = ++j;        else            j = Next[j];    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%s",s);        scanf("%s",p);        int n = strlen(s);        int m = strlen(p);        reverse(s,s + n);        reverse(p,p + m);        GetExtend(s,p);        Getfail(p);        long long ans = 0;        for(int i = 0;i < n;i++)            ans = (ans + 1ll*extend[i]*(extend[i]+1)/2)%MOD;        printf("%lld\n",ans);    }    return 0;}

KMP:待……