HDU 4300 Clairewd’s message

一道KMP的变式

本题仍是求最大前缀后缀,所以仍用KMP,但不同的是,本题有一个密码转换规则,不过好在题目中说了两段不重合,那么我们就可以在中间插入一个特殊符号'*'',保证求next数组时不会越过中线,然后把前半段按对应关系转化成明文,求next数组就行,本题难点在于边界条件的处理。
尽可能向已知或模板靠拢

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAXN=100000+7;
int init(){
	int rv=0,fh=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') fh=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		rv=(rv<<1)+(rv<<3)+c-'0';
		c=getchar();
	}
	return fh*rv;
}
int T,nxt[MAXN],nxt1[MAXN];
char table[400],s[MAXN],ys[400];
void getnxt(){
	nxt1[0]=-1;
	int len=strlen(s);
	int k=-1,j=0;
	while(j<len){
		if(k==-1||s[j]==s[k]) nxt1[++j]=++k;
		else k=nxt1[k];
	}
}
int main(){
	freopen("in.txt","r",stdin);
	T=init();
	while(T--){
		for(int i=1;i<=26;i++){
			scanf(" %c ",&table[i]);
			ys[table[i]-'a'+1]=i+'a'-1;
		}
		scanf("%s",s);
		int len=strlen(s);
		s[len]='*';s[++len]='';
		for(int i=len-1;i>len/2;i--){
			int t=s[i];
			s[i]=s[i-1];s[i-1]=t;
		}
		for(int i=0;i<=len/2-1;i++){
			printf("%c",s[i]);
			s[i]=ys[s[i]-'a'+1];
		}
		getnxt();
		int ans=len-nxt1[len];//cout<<s[ans-1]<<endl;
		if(!(len%2==0&&ans==len/2)){
			for(int i=len/2+1;i<=ans-1;i++) printf("%c",s[i]);
			for(int i=0;i<=ans-1;i++) if(i<len/2) printf("%c",s[i]);else if(i>len/2) printf("%c",ys[s[i]-'a'+1]);
		}else for(int i=0;i<=len/2-1;i++) printf("%c",s[i]);
		printf("
");
	}
	fclose(stdin);
	return 0;
}
原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/7967528.html