zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    jQuery-03
    正则表达式
    文件下载
    Shiro笔记
    MyBatis笔记
    Spring5笔记
    JavaScript笔记
    smartsvn安装和使用 —— svn工具linux版
    网易云歌单导入qq音乐
    svn版本回滚 —— svn使用笔记之三
  • 原文地址:https://www.cnblogs.com/xchaos/p/2419871.html
Copyright © 2011-2022 走看看