• zoj 3587 Marlon's String


    有两个字符串A和B,求多少对属于A的子串组成B。

    若组成B的其中一个子串等于B[0...i](0<=i<n),那么另外一个就等于B[i+1...n-1].所以总共有n-1种形式。

    那么其实就是求B[0...i]和B[i+1...n-1]的值,之后再利用乘法原理求出答案。

    既然是两个串的模式匹配,KMP算法就再适合不过了。

    KMP算法的核心在于p[]数组,p[i]指的是s[0...p[i]]等于s[i-p[i]...i]。

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define MAXN 100010
    using namespace std;

    int p[MAXN];
    char str[MAXN],s[MAXN];
    long long a[MAXN],b[MAXN];

    void getNext(char *s,int *p)
    {
    int i,j;
    j=p[0]=-1;
    for(i=1;s[i]!='\0';i++)
    {
    p[i]=-1;
    while(j>-1&&s[j+1]!=s[i])
    j=p[j];
    if(s[j+1]==s[i])
    {
    j++;
    p[i]=j;
    }
    }
    }

    int main()
    {
    int i,j,t,n,m;
    long long ans;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%s%s",str,s);
    getNext(s,p);
    m=strlen(str);
    n=strlen(s);
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    ans=0;
    for(i=0,j=-1;i<m;i++)
    {
    while(j>-1&&s[j+1]!=str[i])
    j=p[j];
    if(s[j+1]==str[i])
    {
    j++;
    a[j]++;
    }
    }
    for(i=n-1;i>0;i--)
    if(p[i]>-1)
    a[p[i]]+=a[i];

    for(i=0;i+i<m;i++)
    swap(str[i],str[m-1-i]);
    for(i=0;i+i<n;i++)
    swap(s[i],s[n-1-i]);

    getNext(s,p);
    for(i=0,j=-1;i<m;i++)
    {
    while(j>-1&&s[j+1]!=str[i])
    j=p[j];
    if(s[j+1]==str[i])
    {
    j++;
    b[j]++;
    }
    }
    for(i=n-1;i>0;i--)
    if(p[i]>-1)
    b[p[i]]+=b[i];

    for(i=0;i+1<n;i++)
    ans+=a[i]*b[n-2-i];

    printf("%lld\n",ans);
    }
    return 0;
    }
  • 相关阅读:
    树分治
    实现自己的shell--MIT xv6 shell
    逆元打表
    Linux fork()函数
    三分:求解凸函数极值
    anti-nim 游戏
    nginx配置文件详解
    nginx之别名、location使用
    shell脚本编程基础知识点
    linux任务计划
  • 原文地址:https://www.cnblogs.com/xchaos/p/2419871.html
Copyright © 2020-2023  润新知