版权声明:欢迎学习我的博客,希望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完准备写博客了发现我这里写的好像不太对、、)