HDU 3374 String Problem

为什么我要做这么水的题呢,因为我实在是太弱了- -

刚补完数学(水了好多题的样子)于是就来水字符串了,感觉自己这方面的数据结构的知识好少。

只好从KMP开始水了。

于是就看到了这道最小最大表示法+KMP的题。

以前总感觉最小表示法好高端的样子

现在才发现

卧槽真简单啊

要不要这么简单啊

就是搞两个指针,i在前,j在后,以及当前已匹配的长度k,

如果s[i+k]==s[j+k],那么显然k++。

如果s[i+k]>s[j+k],那么可以发现s[i],s[i+1]......s[i+k]都不是最小表示了,所以i->i+k+1。

同理s[i+k]<s[j+k]的时候j->j+k+1。

于是就求完了,复杂度O(N)。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[1000005];
int fail[1000005],n;
void getfail(){
	int j=0;
	for(int i=2;i<=n;i++){
		while(j&&s[j+1]!=s[i])j=fail[j];
		if(s[j+1]==s[i])j++;
		fail[i]=j;
	}
}
int express(bool flag){
	int i=1,j=2,k=0;
	while(i<=n&&j<=n&&k<=n){
		int tmp=s[(i+k-1)%n+1]-s[(j+k-1)%n+1];
		if(!tmp)k++;
		else{
			if(flag){
				if(tmp<0)j+=k+1;
				else i+=k+1;
			}else{
				if(tmp<0)i+=k+1;
				else j+=k+1;
			}
			k=0;
			if(i==j)j++;
		}
	}
	return min(i,j);
}
int main(){
	while(scanf("%s",s+1)==1){
		n=strlen(s+1);
		getfail();
		int ans=n-fail[n];
		ans=n%ans?1:n/ans;
		printf("%d %d %d %d\n",express(true),ans,express(false),ans);
	}
	return 0;
}
			


你可能感兴趣的:(HDU 3374 String Problem)