Clairewd’s message HDU - 4300

2 篇文章 0 订阅

扩展KMP的详细理解

将s2当做密文进行解密为sts2(明+?),完成后将s2(密+明)和sts2进行匹配 。

因为密文解密后即为明文,但是  所给的s2明文不全,所以只可能部分匹配,或不匹配,所以,只需找到匹配的点以及匹配的长度是否大于等于s2.length(),若是,则0-i为密文,明文则在对应的sts2里找。

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

const int N = 100000+5;
const int inf = 0x3f3f3f3f;

int Next[N];//表示为以模式串中以i为起点的后缀字符串和模式串的最长公共前缀长度.
int Extend[N];//表示为以字符串中以i为起点的后缀字符串和模式串的最长公共前缀长度.
string s, t;

void init() {
	memset(Next, 0, sizeof(Next));
	memset(Extend, 0, sizeof(Extend));
}
void GetNext(string s, int len) {
	Next[0] = len;

	int cnt = 0, pos = 0;

	while(cnt<len-1 && s[cnt] == s[cnt+1]) {
		cnt++;
	}
	Next[1] = cnt;
	pos = 1;
	for(int i=2; i<len; i++) {
		int P = pos+Next[pos], L = Next[i-pos];
		if(P <= L+i || P<=i) {
			if(P <= i) {
				P = i;
			}

			while(P < len && s[P] == s[P-i]) {
				P++;
			}

			Next[i] = P-i;
			pos = i;
		} else Next[i] = L;
	}
}

bool GetExtend(string s1, int len1, string s2, int len2) {
//	cout << s1 << " " << s1.length() <<endl << s2 << " " << s2.length() << endl;
	GetNext(s2, len2);

	int cnt = 0, pos;
	
	while(s1[cnt] && s2[cnt] && s1[cnt]==s2[cnt]) {
		cnt++;
	}

	Extend[0] = cnt;
	pos = 0;

	bool flag = false;

	if(cnt == len2) flag=true;

	for(int i=1; i<len1; i++) {
		int P = pos+Extend[pos], L = Next[i-pos];
	//	cout << pos << "+" << Next[pos] << " :" << L << "+" << i << endl; 
		if(P <= L+i || P<=i) {
			if(P <= i) {
				P = i;
			}

			while(P < len1 && s1[P] == s2[P-i]) {
				P++;
			}

			Extend[i] = P-i;
			pos = i;
		} else Extend[i] = L;

		if(Extend[i] == len2) flag = true;
	}
	return flag;
}

int main() {
	int T;
	string s1, s2;

	cin >> T;

	while(T--) {

		init();

		cin >> s1 >> s2;
		int i; 
		
		string sts1(s1.length(), 'a'), sts2(s2.length(), 'a');//必须初始化 
		
		for(i=0; s1[i]; i++) {
			sts1[s1[i]-'a'] = i+'a';
		}
		for(i=0; s2[i]; i++) {
			sts2[i] = sts1[s2[i]-'a'];
		} 
		bool flag = GetExtend(s2, s2.length(), sts2, sts2.length());

		for(i=0; i<s2.length(); i++) {
			
//			cout << i << ": " << Extend[i] << "=" << s2.length() << endl;
			
			if(i+Extend[i]>=s2.length() && i>= Extend[i]) {
				break;
			}
		}
		cout << s2.substr(0, i) << sts2.substr(0, i) << endl;
	}

	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值