Gym

来源:互联网 发布:淘宝复刻wtaps的鲁总 编辑:程序博客网 时间:2024/06/05 11:50

题目链接:https://vjudge.net/problem/Gym-101205D
题意:给你一个字符串递推式(也就是Fibonacci数列),每次输入一个n和一个字符串,问你字符串在f[n]这一项里出现了多少次
解析:首先数据规模很大所以存是存不下的,写了几个数列发现,出现的次数也是一个类似递推式的东西,不过当f[i-1]和f[i-2]拼接起来的时候有可能产生新的可匹配的串,于是分成两部分计数,假设输出的字符串长度为len,那么我们存递推字符串的时候可以存f[i-1]的前len-1项后len-1项,f[i-2]的前len-1项后len-1项,然后再做一次kmp,一只递推到第n项就是答案了,用string写还是(W)很(A)悠(成)闲(傻)的(逼)

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <set>#include <map>#include <queue>using namespace std;const int maxn = 2e5+100;int nex[maxn];long long ans[maxn];string a[maxn],p;void getNex(string a){    int n = a.length();    memset(nex,-1,sizeof(nex));    int k = -1,i = 0;    while(i<n)    {        if(k==-1||a[i]==a[k])        {            i++,k++;            nex[i] = k;        }        else            k = nex[k];    }}long long kmp(string a,string b){    int len1 = a.length();    int len2 = b.length();    getNex(b);    int i=0,j=0;    long long cnt = 0;    while(i<len1&&j<len2)    {        if(a[i]==b[j])        {            i++;            j++;            if(j==len2)            {                cnt++;                j = nex[j];            }        }        else if(j==0)            i++;        else            j = nex[j];    }    return cnt;}int main(){    int T = 1,n;    while(cin>>n>>p)    {        a[0] = "0",a[1] = "1";        int len = p.length();        memset(ans,0,sizeof(ans));        ans[0] = kmp(a[0],p);        ans[1] = kmp(a[1],p);//        cout<<"0"<<" "<<ans[0]<<" "<<a[0]<<endl;//        cout<<"1"<<" "<<ans[0]<<" "<<a[1]<<endl;        for(int i=2;i<=n;i++)        {            int c1 = a[i-1].length();            int c2 = a[i-2].length();            if(c2>len && len!=1)            {                string t1 = a[i-1].substr(0,len-1);                string t2 = a[i-1].substr(c1-len+1,len-1);                string t3 = a[i-2].substr(0,len-1);                string t4 = a[i-2].substr(c2-len+1,len-1);                a[i] = t1+t2+t3+t4;                ans[i] = ans[i-1]+ans[i-2]+kmp(t2+t3,p);            }            else if(len!=1)            {                a[i] = a[i-1]+a[i-2];                ans[i] += kmp(a[i],p);            }            else if(len==1)                ans[i] = ans[i-1]+ans[i-2];        }        printf("Case %d: %I64d\n",T++,ans[n]);    }    return 0;}
0 0
原创粉丝点击