【APIO2016】字符串匹配

Description

这里写图片描述

Solution

刚看到这题,最有想法,这不是一道水题吗!
然后脑抽打了个后缀数组加KMP(其实只用KMP就好了),然后打的又臭又长,最后还爆零了。我的KMP尽然从1开始搜!!!!!TAT
主要思路:分两种情况
1、S比T短,设S在T中出现次数为o,然后答案先加上n*o,然后再找中间出现的次数,设S的长度为m,把T的后m-1个和T的前m-1个组成新的字符串A,然后求得S在A中的出现次数p,然后答案再加上p*(n-1)。
2、S比T长,先把T增添到比S长,假设增添了b次,那么有 nb 个串可以做上面的操作,然后还剩下一些字符串这些字符串肯定比S小,那么就把T的后m-1个串与剩下的串合并,再得出答案相加就好了。
看起来写的很长,其实很简单。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=300007;
int i,j,k,l,t,m,len1,len2,p[maxn],da,len3;
char s[maxn],st[maxn],sr[maxn],sq[maxn],ss[maxn];
int sa[maxn],rank[maxn],height[maxn],zhi[maxn],fu[maxn],q[maxn],w,zuo,you,len4,len5;
int js[maxn];
long long ans,n,nn,bei;
int main(){
    scanf("%lld",&n);
    scanf("%s",s+1);len1=strlen(s+1);
    fo(i,2,len1){
        while(k>0&&s[i]!=s[k+1])k=p[k];
        if(s[i]==s[k+1])k++;
        p[i]=k;
    }
    p[1]=0;
    scanf("%s",st+1);len2=strlen(st+1);
    if(len1<=len2){
        k=0;l=0;
        fo(i,1,len2){
            while(k>0&&st[i]!=s[k+1])k=p[k];
            if(st[i]==s[k+1])k++;
            if(k==len1){
                l++;
                k=p[k];
            }
        }       
        ans=l*n;
        fo(i,len2-len1+2,len2)sr[++len3]=st[i];
        fo(i,1,len1-1)sr[++len3]=st[i];
        k=0;w=0;l=0;
        fo(i,1,len3){
            while(k>0&&sr[i]!=s[k+1])k=p[k];
            if(sr[i]==s[k+1])k++;
            if(k==len1){
                l++;
                k=p[k];
            }
        } 
        ans=ans+l*(n-1);
        printf("%lld\n",ans);
    }
    else{
        while(len41,len2)sq[++len4]=st[i];
        }    
        nn=n/bei;
        k=0;l=0;
        fo(i,1,len4){
            while(k>0&&sq[i]!=s[k+1])k=p[k];
            if(sq[i]==s[k+1])k++;
            if(k==len1){
                k=p[k];
                l++;
            }
        }       
        ans=l*nn;
        fo(i,len4-len1+2,len4)sr[++len3]=sq[i];
        fo(i,1,len1-1)sr[++len3]=sq[i];
        k=0;w=0;l=0;
        fo(i,1,len3){
            while(k>0&&sr[i]!=s[k+1])k=p[k];
            if(sr[i]==s[k+1])k++;
            if(k==len1){
                k=p[k];
                l++;
            }
        } 
        ans=ans+l*(nn-1);
        fo(i,len4-len1+2,len4)ss[++len5]=sq[i];
        fo(j,1,n-nn*bei)fo(i,1,len2)ss[++len5]=st[i];
        k=0;l=0;
        fo(i,1,len5){
            while(k>0&&ss[i]!=s[k+1])k=p[k];
            if(ss[i]==s[k+1])k++;
            if(k==len1){
                k=p[k];
                l++;
            }
        }       
        ans+=l;
        printf("%lld\n",ans);
    }
}

你可能感兴趣的:(字符串,kmp,后缀数组)