列表

详情


NC16126. 小Y的字符串

描述

总所周知的是,小Y对于字符串之类的题目总是很得心应手的,这一天漂亮的学妹问了小Y一个题目,问两个字符串怎样进行字典序大小比较,当然啦,这种题目对于小Y来说简直是太太太太太简单的啦~~~~于是小Y只花了一点时间就和学妹说清楚了。

不过为了和学妹获得更多的相处时间,小Y灵机一动,给学妹提了一道看似简单的问题,问给定一两个字符串a,b,问a里面有多少个子串字典序小于b。

学妹算着算着就迷糊了,于是她向你求助,如果你帮助她解决这个问题,那么可能漂亮的学妹会考虑一下让你做她男朋友哦~~~(题目保证输入全部为小写英文字母)

输入描述

输入两个字符串a,b(1<=|b|<|a|<=200000)。

输出描述

输出一个数,表示a的子串里面有多少个串字典序小于b串。

示例1

输入:

aababac ba

输出:

21

示例2

输入:

bcefeghijklmn df

输出:

25

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 12ms, 内存消耗: 3872K, 提交时间: 2022-11-29 14:07:42

/*
aaaabaa
aaaaa
*/


/*
对题目的理解:
KMP Extension
*/
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
ll z[N];
ll p[N];
char a[N],b[N];
void get_z(char *b,ll blen){
	z[1]=blen;
	for(ll i=2,left,right=0;i<=blen;i++){
		if(i<=right) z[i]=min(z[i-left+1],right-i+1);
		while(b[i+z[i]]==b[1+z[i]]){
			z[i]++;
		}
		if(i+z[i]-1>right){
			left=i;
			right=i+z[i]-1;
		}
	}
}

void get_p(char*b, ll blen,char* a,ll alen){
	for(ll i=1,left,right=0;i<=alen;i++){
		if(i<=right)	p[i]=min(z[i-left+1],right-i+1);
		while(i+p[i]<=alen&&1+p[i]<=alen&&b[1+p[i]]==a[i+p[i]]){
			p[i]++;
		}
		if(i+p[i]-1>right){
			left=i;
			right=i+p[i]-1;
		}
	}
}

int main(){
	cin>>(a+1)>>(b+1);
	ll alen=strlen(a+1);
	ll blen=strlen(b+1);
	get_z(b,blen);
	get_p(b,blen,a,alen);
	ll ans=0;
	for(int i=1;i<=alen;i++){
		ans+=min(p[i],blen-1);
		if(a[i+p[i]]<b[1+p[i]]){
			ans+=alen-(i+p[i])+1;
		}
	}
	cout<<ans<<endl;
    system("pause");
	return 0;
}

C++(clang++11) 解法, 执行用时: 8ms, 内存消耗: 2172K, 提交时间: 2020-10-28 15:48:27

#include<bits/stdc++.h>
using namespace std;
const int M=200009;
int n,m;
long long ans;
char c[M],b[M];
int nex[M],ext[M];
int main(){
	scanf("%s%s",c+1,b+1);
	n=strlen(c+1);
	m=strlen(b+1);
	nex[1]=m;
	for(int i=2,p=1,a=1;i<=m;++i){
		if(i>=p||i+nex[i-a+1]>=p){
			if(i>=p)p=i;
			while(p<=m&&b[p]==b[p-i+1])p++;
			nex[i]=p-i;
			a=i;
		}
		else nex[i]=nex[i-a+1];
	}
	for(int i=1,p=1,a=1;i<=n;++i){
		if(i>=p||i+nex[i-a+1]>=p){
			if(i>=p)p=i;
			while(p<=n&&p-i+1<=m&&c[p]==b[p-i+1])p++;
			ext[i]=p-i;
			a=i;
		}
		else ext[i]=nex[i-a+1];
	}
	for(int i=1;i<=n;++i){
		if(c[i+ext[i]]<b[ext[i]+1]&&ext[i]<m)ans+=1ll*n-i+1;
		else ans+=1ll*min(ext[i],m-1);
	}
	printf("%lld",ans);
	return 0;
}

上一题