【Hihocoder - offer编程练习赛94 - B】字符删除(字典树,dp预处理)

版权声明:欢迎学习我的博客,希望ACM的发展越来越好~ https://blog.csdn.net/qq_41289920/article/details/87984767

题干:

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

给定一个字符串S和包含N个单词的字典D = {W1, W2, .... WN},小Hi想知道他最少从S中删除多少个字符,才能得到一个字典中的单词。

输入

第一行包含一个整数N。  

第二行包含N个空格隔开的单词,单词都由小写字母组成。  

第三行包含字符串S,由小写字母组成。  

1 <= N <= 10000  

字典中单词总长度不超过1000000  

1 <= |S| <= 100000

输入保证一定有解。

输出

一个整数代表答案。

样例输入

5
cat chat hate has heat
sheate

样例输出

2

解题报告:

     拿到题目,想到两种处理方式,1.处理n个串,以n个串建字典树,但是接下来不方便处理。2.处理那个单个的串,预处理出从当前字母到下一个字母的最近位置,算是一种贪心求解。

   显然,第二种思路比较容易思考,,于是写就行了、、

AC代码1:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
string s[MAX],ss;
int trie[MAX][66];
int main()
{
	int n;
	cin>>n;
	for(int i = 1; i<=n; i++) cin>>s[i];
	cin>>ss;
	int len = ss.size();
	ss = ' ' + ss;
	for(int j = 0; j<26; j++) trie[len+1][j] = -1;
	for(int i = len; i>=1; i--) {
		for(int j = 0; j<26; j++) {
			if(j == ss[i] - 'a') trie[i][j] = i;
			else trie[i][j] = trie[i+1][j];
		}
	}
	int ans = 0x3f3f3f3f;
	for(int i = 1; i<=n; i++) {
		int cur = 0;
		int up = s[i].size();
		for(int j = 0; j<up; j++) {
			cur = trie[cur+1][s[i][j] - 'a'];
			if(cur == -1) break;
		}
		if(cur != -1) ans = min(ans,len - up);
	}
	printf("%d\n",ans);
	return 0 ;
 }

注意一个细节,cur从0开始来避免讨论处理的起点。 


AC代码2: 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
string s[MAX],ss;
int trie[MAX][66];
int main()
{
	int n;
	cin>>n;
	for(int i = 1; i<=n; i++) cin>>s[i];
	cin>>ss;
	int len = ss.size();
	ss = ' ' + ss;
	for(int j = 0; j<26; j++) trie[len+1][j] = -1;
	for(int i = len; i>=1; i--) {
		for(int j = 0; j<26; j++) {
			if(j == ss[i] - 'a') trie[i][j] = i;
			else trie[i][j] = trie[i+1][j];
		}
	}
	int ans = 0x3f3f3f3f;
	for(int i = 1; i<=n; i++) {
		int cur = 1;
		int up = s[i].size();
		for(int j = 0; j<up; j++) {
			cur = trie[cur][s[i][j] - 'a'];
			if(cur == -1) break;
		}
		if(cur != -1) ans = min(ans,len - up);
	}
	printf("%d\n",ans);
	return 0 ;
 }

但是其实这份代码是有问题的。

比如:

1
aab
aaac

就过不了了、、、(但是交上可以AC、、A完准备写博客了发现我这里写的好像不太对、、)

猜你喜欢

转载自blog.csdn.net/qq_41289920/article/details/87984767