• Count the string kmp


      

    问题描述
    众所周知,aekdycoin擅长字符串问题和数论问题。当给定一个字符串s时,我们可以写下该字符串的所有非空前缀。例如:
    S:“ABAB”
    前缀是:“A”、“AB”、“ABA”、“ABAB”
    对于每个前缀,我们可以计算它在s中匹配的次数,因此我们可以看到前缀“a”匹配两次,“ab”也匹配两次,“ab a”匹配一次,“ab ab”匹配一次。现在,您需要计算所有前缀的匹配时间之和。对于“abab”,它是2+2+1+1=6。
    答案可能非常大,因此输出答案mod 10007。


    输入
    第一行是一个整数t,表示测试用例的数量。对于每种情况,第一行是一个整数n(1<=n<=200000),它是字符串s的长度。后面的一行给出字符串s。字符串中的字符都是小写字母。


    产量
    对于每种情况,只输出一个数字:s mod 10007所有前缀的匹配时间总和。

    对s进行lens次的分割  然后不断kmp  但是超时了

    #include<bits/stdc++.h>
    using namespace std;
    //input
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m);
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define inf 0x3f3f3f3f
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define N 200000+5
    #define mod 10007
    string s,p;
    int ans;
    int lens,lenp;
    int nex[N];
    void getnext()
    {
        nex[0]=-1;
        int k=-1,j=0;
        while(j<lenp-1)
        {
            if(k==-1||p[j]==p[k])
                nex[++j]=++k;
            else k=nex[k];
        }
    }
    
    int kmp()
    {
        int j=0,i=0;
        while(i<lens&&j<lenp)
        {
            if(s[i]==p[j]||j==-1)
            {
                i++;
                j++;
            }
            else j=nex[j];
            if(j==lenp)
            {
                ans++;j=0;
            }
        }
    }
    
    int main()
    {
        int cas;
        RI(cas);
        while(cas--)
        {
            RI(lens);
            ans=0;
            cin>>s;
            for(lenp=1;lenp<=lens;lenp++)
            {
                p=s.substr(0,lenp);
                getnext();
                kmp();
            }
             cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    显然都200000了  必然会超时的

    这题其实用不到kmp  主要是next数组

    next数组才是kmp的精髓 !!!!!!

    对p进行next扫描

    初始化:cnt=lenp

    如果next为0肯定没有可匹配的

    如果next不为0 肯定有至少一个相匹配的

    如果前后缀没有交集  肯定是一个匹配的

    如果有交集  为1+交集中 相匹配的( 因为交集中的字符串  就是最后的字符串! 这点是本题最重要的  )

    显然 交集的最后一个匹配值为囊括了交集中所有匹配的(而这个值之前已经遍历过了!)

    详情见代码

    #include<bits/stdc++.h>
    using namespace std;
    //input
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m);
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define inf 0x3f3f3f3f
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define N 200000+5
    #define mod 10007
    string s,p;
    int lens,lenp;
    int nex[N];
    int ans[N];
    void getnext()
    {
        nex[0]=-1;
        int k=-1,j=0;
        while(j<lenp)
        {
            if(k==-1||p[j]==p[k])
                nex[++j]=++k;
            else k=nex[k];
        }
    }
    int main()
    {
        int  cas;
        RI(cas);
        while(cas--)
        {
            RI(lenp);
            cin>>p;
            getnext();
            int cnt=lenp;
            rep(i,1,lenp)
            {
                if(!nex[i])continue;
                if(nex[i]*2<=i)
                {
                    cnt++; ans[i]=1; continue;
                }
               cnt++;
               cnt+=ans[nex[i]];
               ans[i]=1+ans[nex[i]];
            }
            cout<<cnt%mod<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Android系统根文件系统目录结构
    4面 晶晨半导体 问题总结
    linux 工作队列
    Linux tasklet 的测试
    ArbotiX-M引脚说明
    locobot
    视频地址
    S1雷达ROS包更新指南
    rospy
    mx-28在 labview环境下的开发
  • 原文地址:https://www.cnblogs.com/bxd123/p/10673113.html
Copyright © 2020-2023  润新知