bzoj 1398 项链 【最小表示法】

盗CA爷的题,学习了最小表示法,最后发现CA爷不是写的这个算法。

但不管了。

最小表示法大致是维护两个指针ij且i!=j 把它们向后扫,直到st[i+k]!=st[j+k] 然后将st较大的那个指针移到x+k+1,如果两个指针相等,任取一个加一。 注意是一个循环字符串,在k=l时退出。

因为vijos上没有JUDGE_ONLINE 这个宏,wa了半天。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>

#define ll long long
#define inf 1e9
#define eps 1e-10
#define md
#define N 2000010
using namespace std;
char st1[N],st2[N];
int get(char st[],int l)
{
	int i=0,j=1;
	while (i<l&&j<l)
	{
		int k=0;
		while (k<l&&st[i+k]==st[j+k]) k++;
		if (k==l) break;
		if (st[i+k]>st[j+k]) i=i+k+1;
		  else j=j+k+1;
		if (i==j) j++;
	//	printf("%d %d\n",i,j);
	} //printf("\n");
	return min(i,j);
}
		

int main()
{
#ifndef ONLINE_JUDGE
	freopen("data.in","r",stdin); freopen("data.out","w",stdout);
#endif
	scanf("%s%s",st1,st2);
	int l1=strlen(st1),l2=strlen(st2);
	for (int i=l1;i<(l1<<1);i++) st1[i]=st1[i-l1]; st1[l1<<1]='\0';
	for (int j=l2;j<(l2<<1);j++) st2[j]=st2[j-l2]; st2[l2<<1]='\0';
	//printf("%s %s\n",st1,st2);
	if (l1!=l2)
	{
		printf("No\n");
	}
	else
	{
		int a=get(st1,l1),b=get(st2,l2);
		//printf("%d %d\n",a,b);
		bool ok=1;
		for (int i=a,j=b,l=1;l<=l1;l++,i++,j++)
		{
			if (st1[i]!=st2[j]) { ok=0; break;}
		}
		if (ok)
		{
			printf("Yes\n");
			for (int i=a,l=1;l<=l1;l++,i++)
			{
				putchar(st1[i]);
			}
			printf("\n");
		}
		else printf("No\n");
	}
	return 0;
}


你可能感兴趣的:(字符串,最小表示法)