codeforces 631d D. Messenger

题意:就是找第二个串在第一个串中出现的次数。

思路:kmp  对于如果T串只有1个或者两个字符就可以直接暴力了。但是对于有三个的字符就不可以了。那么把问题转化一下,就是去掉T串的首字符和尾字符,那么肯定其他的字符一定是相等的并且个数相等,那么我就直接kmp找出去掉首尾后在S中出现的个数,并记录下标,那么就可以最后再judge一下S中的首尾是否大于等于T中的首尾。kmp理解不到位就被kmp耍成傻逼。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int ,int > pii;
const int N =2e5+5;

int n,m;
int nn,mm;
char s[10];
ll cc;
ll cnt[N];
ll cnt1[N];
int num[N];
int num1[N];

int nxt[N];
int tmp[N];
ll tmpc[N];

vector<pii >ve;

void kmp_pre(int T[],ll cc[],int len)
{
	int i,j;
	i=0;
	j=nxt[0]=-1;
	while(i<len)
	{
		while(j!=-1&&( T[i]!=T[j]||cc[i]!=cc[j] )) j=nxt[j];
		nxt[++i]=++j;
	}
}

void kmp_count(int T[],ll c2[],int S[],ll c1[],int len)
{   // 返回T 在S 中出现的次数
	int i,j;
	kmp_pre(T,c2,len);
	i=1; j=0;
	for(i = 1; i <= nn; i++)
    {
        while(j > 0 && ( S[i] != T[j] || c1[i] != c2[j] )) j = nxt[j];
        if(S[i] == T[j] && c1[i] == c2[j]) j++;
        if(j == len)
        {
            //cout<<"id "<<i<<endl;
            //cout<<"L "<<i-len<<" R "<<i+1<<endl;
            ve.push_back(pii(i-len,i+1));
			j = nxt[j];
        }
    }
}


int main()
{
    num[0]=num1[0]=-1;
    scanf("%d %d",&n,&m);

    for(int i=1;i<=n;i++){
        scanf("%lld-%s",&cc,s);
        int id=s[0]-'a'+1;
        if(num[nn]==id){
            cnt[nn]+=cc;
        }
        else{
            num[++nn]=id;
            cnt[nn]=cc;
        }
    }

    for(int i=1;i<=m;i++){
        scanf("%lld-%s",&cc,s);
        int id=s[0]-'a'+1;
        if(num1[mm]==id){
            cnt1[mm]+=cc;
        }
        else{
            num1[++mm]=id;
            cnt1[mm]=cc;
        }
    }

    ll ans=0;
    if(mm==1){
        int id=num1[1];
        cc=cnt1[1];
        for(int i=1;i<=nn;i++){
            if(num[i]==id&&cnt[i]>=cc)
            {
                ans+=1ll*(cnt[i]-cc+1);
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    else if(mm==2){
        for(int i=1;i<nn;i++){
            if(num[i]==num1[1]&&cnt[i]>=cnt1[1]&&num[i+1]==num1[2]&&cnt[i+1]>=cnt1[2]){
                ans++;
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    else{

    	//cout<<"nn "<<nn <<" mm "<<mm<<endl;
    	int len=0;
    	for(int i=2;i<mm;i++){
    		//printf("%c",num1[i]-1+'a');
    		tmp[len]=num1[i];
    		tmpc[len++]=cnt1[i];
    	}

		kmp_count(tmp,tmpc,num,cnt,len);

		int sz=ve.size();

		for(int i=0;i<sz;i++){
			int l,r;
			l=ve[i].first; r=ve[i].second;
			if((num[l]==num1[1]&&cnt[l]>=cnt1[1])&&(num[r]==num1[mm]&&cnt[r]>=cnt1[mm])){
				ans++;
			}
		}

		printf("%lld\n",ans);
    }

    return 0;
}

/*

20 10
1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a
1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b

*/

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/82872326
今日推荐