zoukankan      html  css  js  c++  java
  • A Secret HDU

    题意要你求b串每一个后缀对a串的每一个后缀的匹配长度之和

    将两个串倒过来

    用这时的b串的前缀去匹配a的后缀

    这时候所k处匹配的结果就是以k为终点,有最长可以匹配向后到extend[k]长度

    对于每一个点等差数列求和 累加

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define inf 0x3f3f3f3f
    
    const int maxn=1e6+10;
    
    int mod=1e9+7;
    
    int nxt[maxn],extend[maxn];
    
    int q;
    
    char s[maxn],t[maxn];
    
    
    void getnxt()
    {
        int l=strlen(t);
        nxt[0]=l;
        int now=0;
        while(t[now]==t[now+1]&&now+1<l) now++;
        nxt[1]=now;
        int p0=1;//可以到达最远位置的i
        for(int i=2;i<l;i++)
        {
            if(i+nxt[i-p0]<nxt[p0]+p0)
                nxt[i]=nxt[i-p0];
            else
            {
                int now=nxt[p0]+p0-i;
                now=max(now,0);//这里是为了防止i>p的情况
                while(t[now]==t[i+now]&&i+now<l)
                    now++;
                nxt[i]=now;
                p0=i;
            }
        }
    }
    
    void exkmp()
    {
        getnxt();
        int now=0;
        int l=strlen(s);
        int l1=strlen(t);
        int lim=min(l,l1);
        while(s[now]==t[now]&&now<lim)
            now++;
        extend[0]=now;
        int p0=0;
        for(int i=1;i<l;i++)
        {
            if(i+nxt[i-p0]<extend[p0]+p0)
                extend[i]=nxt[i-p0];
            else
            {
                int now=extend[p0]+p0-i;
                now=max(now,0);
                while(t[now]==s[i+now]&&now<l1&&now+i<l)
                    now++;
                extend[i]=now;
                p0=i;
            }
        }
    }
    
    int main()
    {
        int mub;
        scanf("%d",&mub);
        while(mub--)
        {
            scanf("%s%s",s,t);
            int l=strlen(s);
            int l1=strlen(t);
            reverse(t,t+l1);
            reverse(s,s+l);
    //        cout<<s<<endl;
    //        cout<<t<<endl;
    //        cout<<s<<endl;
    //        cout<<t<<endl;
            mem(nxt,0);
            mem(extend,0);
            exkmp();
            ll ans=0;
            for(int i=0;i<l;i++)
            {
                ans=(ans+(1ll*extend[i]*(extend[i]+1)/2)%mod)%mod;           // ans+=extend[i];
            }
            printf("%d
    ",ans);
            /*int l=t.size(),l1=s.size();
            for(int i=0;i<l;i++)
            {
                cout<<nxt[i]<<" ";
            }cout<<endl;
            for(int i=0;i<l1;i++)
            {
                cout<<extend[i]<<" ";
            }cout<<endl;*/
        }
        return 0;
    }
  • 相关阅读:
    LR杂记-nmon+analyser监控linux系统资源
    accept函数
    android performClick使用
    #line 的作用是改变当前行数和文件名称
    C++常用排序法、随机数
    C语言运算符优先级及结合性
    如何高效把一字节的位对换, bit0和bit7,bit1和bit6,以此类推.
    NumPy
    Rational Rose、PowerDesign、Visio的一些比较
    vld,Bounds Checker,memwatch,mtrace,valgrind,debug_new几种内存泄露检测工具的比较,Valgrind Cheatsheet
  • 原文地址:https://www.cnblogs.com/minun/p/11253881.html
Copyright © 2011-2022 走看看