您的位置:首页 > 其它

【JZOJ4624】字符串匹配

2016-07-14 08:35 393 查看

Description



Solution

诶,这题不是赤裸裸kmp吗?

对于|S|<|T|的情况,直接做kmp,统计答案就行。

那对于普遍情况呢?

我们先复制T串使得|S|<|T|,记这时有k段T串,然后跑一次kmp,得出的答案记为a1,再复制一段T,跑一次kmp,得出的答案记为a2,那么我们很容易求出在此基础上每复制一段所增加的匹配数就为(a2−a1),总匹配数就为:a1+(a2−a1)(n−k)。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
#define ll long long
using namespace std;
int f
;
char s
,T[N*4];
int l1,l2,l3;
void get()
{
int j=0;
fo(i,2,strlen(s+1))
{
while(j>0 && s[j+1]!=s[i]) j=f[j];
if (s[j+1]==s[i]) j++;
f[i]=j;
}
}
int kmp(int l,int r)
{
int j=0;
int ans=0;
fo(i,l,r)
{
while (j>0 && s[j+1]!=T[i]) j=f[j];
if (s[j+1]==T[i]) j++;
if (j==l1)
{
ans++;
j=f[j];
}
}
return ans;
}
int main()
{
freopen("4624.in","r",stdin);
freopen("4624.out","w",stdout);
ll n;
cin>>n;
cin>>s+1;
cin>>T+1;
get();
l1=strlen(s+1),l2=strlen(T+1),l3=l2;
n--;
while(l3<=l1 && n)
{
n--;
fo(i,l3+1,l2+l3) T[i]=T[i-l2];
l3+=l2;
}
int t1=kmp(1,l3);
fo(i,l3+1,l3+l2) T[i]=T[i-l3];
l3+=l2;
int t2=kmp(1,l3);
cout<<t1*1ll+(t2-t1)*1ll*n;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: