列表

详情


NC20033. [HNOI2004]L语言

描述

标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的。现在你要处理的就是一段没有标点的文章。 一段文章T是由若干小写字母构成。一个单词W也是由若干小写字母构成。一个字典D是若干个单词的集合。 我们称一段文章T在某个字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一个部分都是字典D中的单词。 
例如字典D中包括单词{‘is’, ‘name’, ‘what’, ‘your’},则文章‘whatisyourname’是在字典D下可以被理解的 因为它可以分成4个单词:‘what’, ‘is’, ‘your’, ‘name’,且每个单词都属于字典D,而文章‘whatisyouname’ 在字典D下不能被理解,但可以在字典D’=D+{‘you’}下被理解。这段文章的一个前缀‘whatis’,也可以在字典D下被理解 而且是在字典D下能够被理解的最长的前缀。 
给定一个字典D,你的程序需要判断若干段文章在字典D下是否能够被理解。 并给出其在字典D下能够被理解的最长前缀的位置。

输入描述

输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。
之后的n行每行描述一个单词,再之后的m行每行描述一段文章。
其中1 ≤ n, m ≤ 20,每个单词长度不超过10,每段文章长度不超过1M。

输出描述

对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置。

示例1

输入:

4 3
is
name
what
your
whatisyourname
whatisyouname
whaisyourname

输出:

14
6
0

说明:

整段文章’whatisyourname’都能被理解
前缀’whatis’能够被理解
没有任何前缀能够被理解

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 286ms, 内存消耗: 125848K, 提交时间: 2020-09-06 09:06:38

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
#define re register
const int max_n = 2e6 + 100;
struct node {
	bool IsWard = false;
	map<char, int> childs;
}ns[max_n];
int sz = 1;
char val[max_n];
inline void insert(string& s) {
	int u = 1;
	for (re int i = 0;i < s.size();++i) {
		if (!ns[u].childs[s[i]])
			ns[u].childs[s[i]] = ++sz;
		u = ns[u].childs[s[i]];
	}ns[u].IsWard = true;
}

bool used[max_n];
inline int search(int st,string& s) {
	int u = 1;int ans = st;
	for (re int i = st;i < s.size();++i) {
		if (!ns[u].childs[s[i]])return ans;
		u = ns[u].childs[s[i]];
		if (ns[u].IsWard && !used[i]) {
			used[i] = true;
			ans = max(ans, search(i + 1, s));
		}
	}return ans;
}
int main() {
	ios::sync_with_stdio(0);
	int n, m;cin >> n >> m;
	string s;
	for (re int i = 0;i < n;++i) {
		cin >> s;
		insert(s);
	}for (re int i = 0;i < m;++i) {
		cin >> s;
		fill(used, used + s.size(), 0);
		cout << search(0, s) << endl;
	}
}

C++ 解法, 执行用时: 240ms, 内存消耗: 3448K, 提交时间: 2021-12-05 17:05:19

#include<bits/stdc++.h>
using namespace std;
int trie[300][26],tot;
char s[1 << 20 + 1];
bool flag[300],ff[1 << 20 + 1];
int f(){
	memset(ff,0,sizeof(ff));
	int ans = 0,t,i,j;
	ff[0] = 1;
	for (i = 0;s[i];i++){
		if (ff[i]){
			t = 0;
			for (j = i + 1;s[j];j++){
				t = trie[t][s[j] - 'a'];
				if (!t)break;
				if (flag[t]){
					ans = max(ans,j);
					ff[j] = 1;
				}
			}
		}
	}
	return ans;
}
int main(){
	int n,m,r,i,*p;
	cin>>n>>m;
	while (n--){
		cin>>s;
		r = 0;
		for (i = 0;s[i];i++){
			p = &trie[r][s[i] - 'a'];
			if (!*p)*p = ++tot;
			r = *p;
		}
		flag[r] = 1;
	}
	while (m--){
		cin>>s + 1;
		cout<<f()<<endl;
	}
	return 0;
}

上一题