Word(暴力)

Word

题目大意

给你几个字符串,你要你找一个长度为 l 的串。
保证它可以跟每个字符串匹配,保证这个串有且只有一个。
然后匹配就是字符串存在一个长度为 l 的子串跟它一一匹配不想到的位数不超过 d 个,d 给出。

思路

这题其实可以直接暴力。
就直接选一个字符串(选最短的更优),先枚举子串,然后直接拿这个子串直接去匹配,然后如果不行就换一个字符,换到次数上限就退出。

然后是可以过的,选最短的还跑得挺快。

代码

#include<cstdio>
#include<bitset>
#include<cstring>

using namespace std;

int l, d, sn[31], minn, minx, b[31][55];
char a[31][55];
int ck[11], n;
bool yes;

void dfs(int uc, int x) {
	if (uc > d) return ;
	yes = 1;
	for (int i = 2; i <= n; i++) {//匹配
		int df = 101;
		for (int j = 1; j + l - 1 <= sn[i]; j++) {
			int num = 0;
			for (int k = 1; k <= l; k++)
				if (ck[k] != b[i][j + k - 1]) {
					num++;
					if (num >= df) break;
				}
			df = min(df, num);
		}
		if (df > d) {
			yes = 0;
			break;
		}
	}
	if (yes) return ;
	for (int i = x; i <= l; i++) {//换一个字符
		int rem = ck[i];
		for (int j = 0; j <= 26; j++) {
			if (rem == j) continue;
			ck[i] = j;
			dfs(uc + 1, i + 1);
			if (yes) return ;
			ck[i] = rem;
		}
	}
}

void write() {
	for (int i = 1; i <= l; i++)
		if (ck[i] == 26) putchar(' ');
			else putchar(ck[i] + 'a');
}

int main() {
//	printf("%.3lf", (sizeof(t)) / 1024.0);
	minn = 100; minx = 0;
	
	scanf("%d %d", &l, &d);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		sn[i] = 0;
		a[i][sn[i] + 1] = getchar();
		while (a[i][sn[i] + 1] != ' ' && (a[i][sn[i] + 1] < 'a' || a[i][sn[i] + 1] > 'z')) a[i][sn[i] + 1] = getchar();
		while (a[i][sn[i] + 1] == ' ' || (a[i][sn[i] + 1] >= 'a' && a[i][sn[i] + 1] <= 'z')) {
			sn[i]++;
			a[i][sn[i] + 1] = getchar();
		}
		a[i][sn[i] + 1] = 0;
		for (int j = 1; j <= sn[i]; j++)
			if (a[i][j] == ' ') b[i][j] = 26;
				else b[i][j] = a[i][j] - 'a';
		if (sn[i] < minn) {
			minn = sn[i];
			minx = i;
		}
	}
	
	for (int i = 1; i <= sn[1]; i++)//根据最小的建立初始串,这样可以很快
		swap(b[1][i], b[minx][i]);
	swap(sn[1], sn[minx]);
	
	for (int i = l; i <= sn[1]; i++) {
		for (int j = i - l + 1; j <= i; j++)
			ck[j - i + l] = b[1][j];
		dfs(0, 1);
		if (yes) {
			write();
			return 0;
		}
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值