zoukankan      html  css  js  c++  java
  • ZOJ 3587 扩展KMP

    思路:这题确实大帝做得非常机智!字符串先求最长前缀,反的字符串再求一次最长前缀。然后就能够搞了。

    每一个子串出现的次数就是最长前缀的次数嘛!

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<bitset>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson i<<1,l,mid
    #define rson i<<1|1,mid+1,r
    #define llson j<<1,l,mid
    #define rrson j<<1|1,mid+1,r
    #define INF 0x7fffffff
    #define maxn 100005
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    void EKMP(char *s,char *t,ll *next,ll *extend)//s[]为主串,t[]为模版串
    {
        int i,j,p,l;
        int len=strlen(t);
        int len1=strlen(s);
        memset(next,0,sizeof(next));
        memset(extend,0,sizeof(extend));
        next[0]=len;
        j=0;
        while(1+j<len&&t[j]==t[1+j])j++;
        next[1]=j;
        int a=1;
        for(i=2; i<len; i++)
        {
            p=next[a]+a-1;
            l=next[i-a];
            if(i+l<p+1)next[i]=l;
            else
            {
                j=max(0,p-i+1);
                while(i+j<len&&t[i+j]==t[0+j])j++;
                next[i]=j;
                a=i;
            }
        }
        j=0;
        while(j<len1&&j<len&&s[j]==t[j])j++;
        extend[0]=j;
        a=0;
        for(i=1; i<len1; i++)
        {
            p=extend[a]+a-1;
            l=next[i-a];
            if(l+i<p+1)extend[i]=next[i-a];
            else
            {
                j=max(0,p-i+1);
                while(i+j<len1&&j<len&&s[i+j]==t[j])j++;
                extend[i]=j;
                a=i;
            }
        }
    }
    char S[maxn],T[maxn];
    ll next[maxn],extend[maxn],sum[maxn],sum1[maxn];
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            mem(sum,0);mem(sum1,0);
            scanf("%s%s",S,T);
            EKMP(S,T,next,extend);
            int len1=strlen(S),len2=strlen(T);
            for(int i=0;i<len1;i++)
                sum[extend[i]]++;
            for(int i=len2-1;i>=1;i--)
                sum[i]+=sum[i+1];
            reverse(S,S+len1);
            reverse(T,T+len2);
            EKMP(S,T,next,extend);
            for(int i=0;i<len1;i++)
                sum1[extend[i]]++;
            for(int i=len2-1;i>=1;i--)
                sum1[i]+=sum1[i+1];
            ll ans=0;
            for(int i=1;i<len2;i++)
                ans+=sum[i]*sum1[len2-i];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    /*
    2
    aaabbb
    ab
    ababaabaaaab
    abaab
    */
    



  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6710693.html
Copyright © 2011-2022 走看看