萌新刚学OI简单字符串求调(玄关)
查看原帖
萌新刚学OI简单字符串求调(玄关)
556545
_anll_楼主2024/7/12 10:23

rt,按照题解第二篇的思路写的,有些地方不同,WA#12,求 dalao 救救QAQ

#include<vector>
#include<iostream>
#define C 1145141
#define int long long
#define mod 1000000007
#define ull unsigned long long
using namespace std;
const int N=1e6+5;
int n,now,las,ans,len[2],dp[2][N],id[2][N];
ull pow[N],has[2][N];
string s[2];
void init(){
	pow[0]=1;
	for(int i=1;i<=1000000;i++) pow[i]=pow[i-1]*C;
}
ull Find(int pl,int pos,int x){
	if(pos>x) return has[pl][x];
	x+=1;//会因为pos导致顺延 
	return (has[pl][x]-has[pl][pos]*pow[x-pos])+has[pl][pos-1]*pow[x-(pos+1)+1];
}
bool ok(int pos1,int pos2){
	int a=len[now],b=len[las];
	int l=1,r=min(a,b)-1,an=C,mid;
	while(l<=r){
		mid=(l+r)/2;
		if(Find(now,pos1,mid)==Find(las,pos2,mid)) l=mid+1;
		else r=mid-1,an=mid;
	}
	if(an==C) return 1;
	return ((an<pos1||an>=a)?s[now][an]:s[now][an+1])>=
		   ((an<pos2||an>=b)?s[las][an]:s[las][an+1]);
}
void work(int op){
	int l=1,r=len[now],p=1;
	for(int i=1;i<s[op].size();i++)
		has[op][i]=has[op][i-1]*C+(s[op][i]-'a'+1);
	for(int i=1;i<=len[now];i++){
		if(s[op][i]>s[op][i+1]){
			for(int j=p;j<=i;j++) id[op][l++]=j;
			p=i+1;
		}
		else if(s[op][i]<s[op][i+1]){
			for(int j=i;j>=p;j--) id[op][r--]=j;
			p=i+1;
		}
	}
	for(int j=p;j<=len[now];j++) id[op][l++]=j;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;init();
	for(int i=1;i<=n;i++){
		las=now;now=las^1;
		cin>>s[now];s[now]='6'+s[now]+'.';len[now]=s[now].size()-1;work(now);
		if(i==1){
			for(int i=1;i<=len[now];i++) dp[now][i]=1;
			continue;
		}
		for(int j=1,k=1;j<=len[now];j++){
			dp[now][j]=dp[now][j-1];
			while(k<=len[las]&&ok(id[now][j],id[las][k])){
				dp[now][j]=(dp[now][j]+dp[las][k++])%mod;
			}
		}
	}
	for(int i=1;i<=len[now];i++) ans=(ans+dp[now][i])%mod;
	cout<<ans;
	return 0;
}
2024/7/12 10:23
加载中...