hdu 3336 Count the string

      之前发现把题目的网页复制过来显的文章不太好,以后就不这么做了。杭州回来跟死了一样,发誓我要踏踏实实一步一步来。

      这个题是kmp的题,题目意思大概是对于原串中的每个前缀,找这个前缀在原串中出现过几次,对每个前缀都这么做,并用一个计数器来累加,最后要输出的就是这个结果%10007。这个题我tle了一次,主要是现在已经懒得算什么时间复杂度了,之前赛场上我队友非要n^2搞一个一百亿的数据量,我无语到吐血。。。

tle代码:主要思想就是搞出来每个前缀并与原串进行KMP,时间复杂度不是很清楚,反正是挂掉了。后来自己胡乱想了一个想法,就是next数组搞出来的是前后缀问题,那么我就可以考察next数组,看对于其中的每一位会用它进行几次匹配。自己瞎想的,说不清楚,看之后的ac代码哇。

View Code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn=200000+5;

char s[maxn];
string str;
int n,ans,len,next[maxn];

void init()
{
    ans=0;
    memset(s,0,(n+5)*sizeof(char));
}

void data_in()
{
    getchar();
    scanf("%s",s);
//    cout<<s<<endl;
}

void get_next()
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<len)
    {
        if(j==-1||s[i]==s[j])
            i++,j++,next[i]=j;
        else
            j=next[j];
    }
}

void KMP()
{
    int j=-1;
    for(int i=0;i<len;i++)
    {
        while(j>-1&&str[j+1]!=s[i])
            j=next[j];
        if(str[j+1]==s[i]) j++;
        if(j==str.length()-1)
        {
            ans++;
            j=next[j];
        }
    }
}

void cal()
{
    len=strlen(s);
    get_next();
//    for(int i=0;i<=len;i++)
//        cout<<next[i]<<endl;
//    cout<<endl;
    for(int i=0;i<len;i++)
    {
        str="";
        for(int j=0;j<=i;j++)
            str+=s[j];
//        cout<<str<<endl;
        KMP();
    }
    printf("%d\n",ans);
}

int main()
{
    int ncas;
    scanf("%d",&ncas);
    while(ncas--)
    {
        scanf("%d",&n);
        init();
        data_in();
        cal();
    }
    return 0;
}

ac代码:

View Code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn=200000+5;

char s[maxn];
string str;
int n,ans,len,next[maxn];

void init()
{
    ans=0;
    memset(s,0,(n+5)*sizeof(char));
}

void data_in()
{
    getchar();
    scanf("%s",s);
//    cout<<s<<endl;
}

void get_next()
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<len)
    {
        if(j==-1||s[i]==s[j])
            i++,j++,next[i]=j;
        else
            j=next[j];
    }
}

void cal()
{
    len=strlen(s);
    get_next();
//    for(int i=0;i<=len;i++)
//        cout<<next[i]<<endl;
//    cout<<endl;
    for(int i=len;i>=0;i--)
    {
        int j=i;
        while(next[j]!=-1)
        {
            ans++;
            j=next[j];
        }
    }
    printf("%d\n",ans%10007);
}

int main()
{
    int ncas;
    scanf("%d",&ncas);
    while(ncas--)
    {
        scanf("%d",&n);
        init();
        data_in();
        cal();
    }
    return 0;
}

以后会每天都来博客转转,在我的那本书:柔性字符串匹配,回来之前或者回来以后,我都会接着把kmp,字典树,ac自动机,后缀自动机的题目一一找来做,自己先思考,是在做不出再去百度题解。我相信自己,虽然我已经想好了要放弃了,但还在坚持,因为我该做的还没有做完,内心深处给自己布置的那几本书还没有看完。总之就一切跟着刷题转。我qq405948382,有兴趣的朋友一起哇,我是菜鸟,求组队,但是不求虐,伤不起了!

原文地址:https://www.cnblogs.com/RainingDays/p/2760605.html